You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2013/05/30 22:36:19 UTC

[lucy-commits] [01/26] git commit: refs/heads/separate-clownfish-wip2 - Rename Lucy prefixes in Perl bindings to Clownfish

Updated Branches:
  refs/heads/separate-clownfish-wip2 [created] 3da6ebd3f


Rename Lucy prefixes in Perl bindings to Clownfish


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/4d9f129c
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/4d9f129c
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/4d9f129c

Branch: refs/heads/separate-clownfish-wip2
Commit: 4d9f129c6f6452eae6e1e36b195aa6ab60c60add
Parents: 6cfc629
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun May 19 21:56:06 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:16 2013 +0200

----------------------------------------------------------------------
 clownfish/compiler/src/CFCBindAliases.c    |   66 ++++++++-
 clownfish/compiler/src/CFCPerlTypeMap.c    |   28 ++++-
 perl/buildlib/Lucy/Build/Binding/Index.pm  |   14 +-
 perl/buildlib/Lucy/Build/Binding/Misc.pm   |   18 ++--
 perl/buildlib/Lucy/Build/Binding/Object.pm |  170 +++++++++++-----------
 perl/buildlib/Lucy/Build/Binding/Search.pm |    6 +-
 perl/buildlib/Lucy/Build/Binding/Util.pm   |   10 +-
 perl/xs/Lucy/Analysis/RegexTokenizer.c     |   26 ++--
 perl/xs/Lucy/Document/Doc.c                |   80 ++++++------
 perl/xs/Lucy/Index/DocReader.c             |    8 +-
 perl/xs/Lucy/Index/Inverter.c              |   48 +++---
 perl/xs/XSBind.h                           |   22 ++--
 12 files changed, 286 insertions(+), 210 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/clownfish/compiler/src/CFCBindAliases.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCBindAliases.c b/clownfish/compiler/src/CFCBindAliases.c
index 0354080..c32f925 100644
--- a/clownfish/compiler/src/CFCBindAliases.c
+++ b/clownfish/compiler/src/CFCBindAliases.c
@@ -32,45 +32,64 @@ struct alias aliases[] = {
     {"cfish_Obj_get_refcount", "lucy_Obj_get_refcount"},
     {"cfish_Obj_inc_refcount", "lucy_Obj_inc_refcount"},
     {"cfish_Obj_to_host", "lucy_Obj_to_host"},
+    {"Cfish_Obj_Dec_RefCount", "Lucy_Obj_Dec_RefCount"},
+    {"Cfish_Obj_Deserialize", "Lucy_Obj_Deserialize"},
     {"Cfish_Obj_Destroy", "Lucy_Obj_Destroy"},
     {"Cfish_Obj_Destroy_OFFSET", "Lucy_Obj_Destroy_OFFSET"},
     {"Cfish_Obj_Destroy_t", "Lucy_Obj_Destroy_t"},
     {"Cfish_Obj_Dump", "Lucy_Obj_Dump"},
     {"Cfish_Obj_Get_Class_Name", "Lucy_Obj_Get_Class_Name"},
+    {"Cfish_Obj_Inc_RefCount", "Lucy_Obj_Inc_RefCount"},
     {"Cfish_Obj_Is_A", "Lucy_Obj_Is_A"},
     {"Cfish_Obj_Load", "Lucy_Obj_Load"},
     {"Cfish_Obj_Load_OFFSET", "Lucy_Obj_Load_OFFSET"},
     {"Cfish_Obj_Load_t", "Lucy_Obj_Load_t"},
+    {"Cfish_Obj_Serialize", "Lucy_Obj_Serialize"},
     {"Cfish_Obj_To_F64", "Lucy_Obj_To_F64"},
     {"Cfish_Obj_To_I64", "Lucy_Obj_To_I64"},
     {"Cfish_Obj_To_Bool", "Lucy_Obj_To_Bool"},
     {"Cfish_Obj_To_Host", "Lucy_Obj_To_Host"},
-    {"Cfish_Obj_Dec_RefCount", "Lucy_Obj_Dec_RefCount"},
-    {"Cfish_Obj_Inc_RefCount", "Lucy_Obj_Inc_RefCount"},
 
     {"cfish_ByteBuf", "lucy_ByteBuf"},
     {"CFISH_BYTEBUF", "LUCY_BYTEBUF"},
-    {"Cfish_BB_Get_Size", "Lucy_BB_Get_Size"},
+    {"cfish_BB_init", "lucy_BB_init"},
+    {"Cfish_BB_Deserialize", "Lucy_BB_Deserialize"},
     {"Cfish_BB_Get_Buf", "Lucy_BB_Get_Buf"},
+    {"Cfish_BB_Get_Size", "Lucy_BB_Get_Size"},
+    {"Cfish_BB_Mimic_Bytes", "Lucy_BB_Mimic_Bytes"},
+    {"Cfish_BB_To_Host", "Lucy_BB_To_Host"},
+    {"cfish_ViewByteBuf", "lucy_ViewByteBuf"},
+    {"cfish_ViewBB_new", "lucy_ViewBB_new"},
+    {"Cfish_ViewBB_Assign_Bytes", "Lucy_ViewBB_Assign_Bytes"},
 
     {"cfish_CharBuf", "lucy_CharBuf"},
     {"CFISH_CHARBUF", "LUCY_CHARBUF"},
+    {"cfish_CB_clone", "lucy_CB_clone"},
     {"cfish_CB_newf", "lucy_CB_newf"},
     {"cfish_CB_new_from_trusted_utf8", "lucy_CB_new_from_trusted_utf8"},
+    {"cfish_CB_init", "lucy_CB_init"},
+    {"Cfish_CB_Cat_Trusted_Str", "Lucy_CB_Cat_Trusted_Str"},
     {"Cfish_CB_Clone", "Lucy_CB_Clone"},
+    {"Cfish_CB_Deserialize", "Lucy_CB_Deserialize"},
+    {"Cfish_CB_Find_Str", "Lucy_CB_Find_Str"},
+    {"Cfish_CB_Get_Ptr8", "Lucy_CB_Get_Ptr8"},
+    {"Cfish_CB_Get_Size", "Lucy_CB_Get_Size"},
+    {"Cfish_CB_Mimic_Str", "Lucy_CB_Mimic_Str"},
     {"Cfish_CB_Nip_One_OFFSET", "Lucy_CB_Nip_One_OFFSET"},
     {"Cfish_CB_Nip_One_t", "Lucy_CB_Nip_One_t"},
+    {"Cfish_CB_To_Host", "Lucy_CB_To_Host"},
+    {"cfish_ViewCharBuf", "lucy_ViewCharBuf"},
+    {"CFISH_VIEWCHARBUF", "LUCY_VIEWCHARBUF"},
+    {"cfish_ViewCB_new_from_trusted_utf8", "lucy_ViewCB_new_from_trusted_utf8"},
+    {"Cfish_ViewCB_Assign_Str", "Lucy_ViewCB_Assign_Str"},
     {"cfish_ZombieCharBuf", "lucy_ZombieCharBuf"},
     {"CFISH_ZOMBIECHARBUF", "LUCY_ZOMBIECHARBUF"},
-    {"CFISH_VIEWCHARBUF", "LUCY_VIEWCHARBUF"},
     {"cfish_ZCB_new", "lucy_ZCB_new"},
     {"cfish_ZCB_size", "lucy_ZCB_size"},
     {"cfish_ZCB_wrap", "lucy_ZCB_wrap"},
     {"cfish_ZCB_wrap_str", "lucy_ZCB_wrap_str"},
     {"Cfish_ZCB_Assign_Str", "Lucy_ZCB_Assign_Str"},
     {"Cfish_ZCB_Assign_Trusted_Str", "Lucy_ZCB_Assign_Trusted_Str"},
-    {"Cfish_CB_Get_Ptr8", "Lucy_CB_Get_Ptr8"},
-    {"Cfish_CB_Get_Size", "Lucy_CB_Get_Size"},
 
     {"CFISH_FLOATNUM", "LUCY_FLOATNUM"},
     {"CFISH_INTNUM", "LUCY_INTNUM"},
@@ -112,11 +131,15 @@ struct alias aliases[] = {
     {"cfish_Hash", "lucy_Hash"},
     {"CFISH_HASH", "LUCY_HASH"},
     {"cfish_Hash_new", "lucy_Hash_new"},
+    {"cfish_Hash_fetch", "lucy_Hash_fetch"},
+    {"cfish_Hash_store", "lucy_Hash_store"},
+    {"Cfish_Hash_Deserialize", "Lucy_Hash_Deserialize"},
+    {"Cfish_Hash_Fetch_Str", "Lucy_Hash_Fetch_Str"},
     {"Cfish_Hash_Iterate", "Lucy_Hash_Iterate"},
     {"Cfish_Hash_Next", "Lucy_Hash_Next"},
-    {"Cfish_Hash_Fetch_Str", "Lucy_Hash_Fetch_Str"},
     {"Cfish_Hash_Store_Str", "Lucy_Hash_Store_Str"},
     {"Cfish_Hash_Store", "Lucy_Hash_Store"},
+    {"Cfish_Hash_To_Host", "Lucy_Hash_To_Host"},
 
     {"cfish_LockFreeRegistry", "lucy_LockFreeRegistry"},
     {"CFISH_LOCKFREEREGISTRY", "LUCY_LOCKFREEREGISTRY"},
@@ -130,6 +153,17 @@ struct alias aliases[] = {
     {"cfish_Memory_wrapped_malloc", "lucy_Memory_wrapped_malloc"},
     {"cfish_Memory_wrapped_realloc", "lucy_Memory_wrapped_realloc"},
 
+    {"cfish_Float32", "lucy_Float32"},
+    {"cfish_Float32_init", "lucy_Float32_init"},
+    {"Cfish_Float32_Set_Value", "Lucy_Float32_Set_Value"},
+    {"cfish_Float64", "lucy_Float64"},
+    {"cfish_Float64_init", "lucy_Float64_init"},
+    {"Cfish_Float64_Set_Value", "Lucy_Float64_Set_Value"},
+    {"cfish_Integer32", "lucy_Integer32"},
+    {"Cfish_Int32_Set_Value", "Lucy_Int32_Set_Value"},
+    {"cfish_Integer64", "lucy_Integer64"},
+    {"Cfish_Int64_Set_Value", "Lucy_Int64_Set_Value"},
+
     {"cfish_NumUtil_decode_bigend_f32", "lucy_NumUtil_decode_bigend_f32"},
     {"cfish_NumUtil_decode_bigend_f64", "lucy_NumUtil_decode_bigend_f64"},
     {"cfish_NumUtil_decode_bigend_u16", "lucy_NumUtil_decode_bigend_u16"},
@@ -160,6 +194,8 @@ struct alias aliases[] = {
     {"cfish_NumUtil_u4shifts", "lucy_NumUtil_u4shifts"},
     {"cfish_NumUtil_skip_cint", "lucy_NumUtil_skip_cint"},
 
+    {"cfish_StrHelp_to_base36", "lucy_StrHelp_to_base36"},
+    {"cfish_StrHelp_utf8_valid", "lucy_StrHelp_utf8_valid"},
     {"cfish_StrHelp_UTF8_COUNT", "lucy_StrHelp_UTF8_COUNT"},
 
     {"cfish_TestBatch_fail", "lucy_TestBatch_fail"},
@@ -173,29 +209,43 @@ struct alias aliases[] = {
     {"cfish_TestFormatter", "lucy_TestFormatter"},
     {"cfish_TestFormatterCF", "lucy_TestFormatterCF"},
     {"cfish_TestFormatterCF_new", "lucy_TestFormatterCF_new"},
+    {"cfish_TestFormatterTAP", "lucy_TestFormatterTAP"},
+    {"cfish_TestFormatterTAP_new", "lucy_TestFormatterTAP_new"},
 
     {"cfish_VArray", "lucy_VArray"},
     {"CFISH_VARRAY", "LUCY_VARRAY"},
     {"cfish_VA_new", "lucy_VA_new"},
+    {"cfish_VA_store", "lucy_VA_store"},
+    {"Cfish_VA_Clone", "Lucy_VA_Clone"},
+    {"Cfish_VA_Delete", "Lucy_VA_Delete"},
+    {"Cfish_VA_Deserialize", "Lucy_VA_Deserialize"},
     {"Cfish_VA_Fetch", "Lucy_VA_Fetch"},
     {"Cfish_VA_Get_Size", "Lucy_VA_Get_Size"},
+    {"Cfish_VA_Pop", "Lucy_VA_Pop"},
+    {"Cfish_VA_Push", "Lucy_VA_Push"},
     {"Cfish_VA_Resize", "Lucy_VA_Resize"},
+    {"Cfish_VA_Shallow_Copy", "Lucy_VA_Shallow_Copy"},
+    {"Cfish_VA_Shift", "Lucy_VA_Shift"},
     {"Cfish_VA_Store", "Lucy_VA_Store"},
-    {"Cfish_VA_Push", "Lucy_VA_Push"},
+    {"Cfish_VA_To_Host", "Lucy_VA_To_Host"},
 
     {"cfish_VTable", "lucy_VTable"},
     {"CFISH_VTABLE", "LUCY_VTABLE"},
     {"cfish_VTable_add_alias_to_registry", "lucy_VTable_add_alias_to_registry"},
     {"cfish_VTable_bootstrap", "lucy_VTable_bootstrap"},
+    {"cfish_VTable_fetch_vtable", "lucy_VTable_fetch_vtable"},
     {"cfish_VTable_find_parent_class", "lucy_VTable_find_parent_class"},
     {"cfish_VTable_foster_obj", "lucy_VTable_foster_obj"},
     {"cfish_VTable_fresh_host_methods", "lucy_VTable_fresh_host_methods"},
     {"cfish_VTable_init_obj", "lucy_VTable_init_obj"},
+    {"cfish_VTable_init_registry", "lucy_VTable_init_registry"},
     {"cfish_VTable_make_obj", "lucy_VTable_make_obj"},
     {"cfish_VTable_offset_of_parent", "lucy_VTable_offset_of_parent"},
     {"cfish_VTable_register_with_host", "lucy_VTable_register_with_host"},
+    {"cfish_VTable_registry", "lucy_VTable_registry"},
     {"cfish_VTable_singleton", "lucy_VTable_singleton"},
     {"cfish_VTable_to_host", "lucy_VTable_to_host"},
+    {"Cfish_VTable_Foster_Obj", "Lucy_VTable_Foster_Obj"},
     {"Cfish_VTable_Get_Name", "Lucy_VTable_Get_Name"},
     {"Cfish_VTable_Make_Obj", "Lucy_VTable_Make_Obj"},
     {"Cfish_VTable_To_Host", "Lucy_VTable_To_Host"},

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/clownfish/compiler/src/CFCPerlTypeMap.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCPerlTypeMap.c b/clownfish/compiler/src/CFCPerlTypeMap.c
index ce05145..22b0f15 100644
--- a/clownfish/compiler/src/CFCPerlTypeMap.c
+++ b/clownfish/compiler/src/CFCPerlTypeMap.c
@@ -214,7 +214,7 @@ static const char typemap_start[] =
     "uint32_t\tCHY_UNSIGNED_INT\n"
     "uint64_t\tCHY_BIG_UNSIGNED_INT\n"
     "\n"
-    "const lucy_CharBuf*\tCONST_CHARBUF\n";
+    "const cfish_CharBuf*\tCONST_CHARBUF\n";
 
 
 static const char typemap_input[] =
@@ -275,6 +275,32 @@ CFCPerlTypeMap_write_xs_typemap(CFCHierarchy *hierarchy) {
         const char *full_struct_sym = CFCClass_full_struct_sym(klass);
         const char *vtable_var      = CFCClass_full_vtable_var(klass);
 
+        /* Temporary hack until the Clownfish parcel is ready. */
+        if (strcmp(full_struct_sym, "lucy_ByteBuf") == 0) {
+            full_struct_sym = "cfish_ByteBuf";
+            vtable_var      = "CFISH_BYTEBUF";
+        }
+        else if (strcmp(full_struct_sym, "lucy_CharBuf") == 0) {
+            full_struct_sym = "cfish_CharBuf";
+            vtable_var      = "CFISH_CHARBUF";
+        }
+        else if (strcmp(full_struct_sym, "lucy_Hash") == 0) {
+            full_struct_sym = "cfish_Hash";
+            vtable_var      = "CFISH_HASH";
+        }
+        else if (strcmp(full_struct_sym, "lucy_Obj") == 0) {
+            full_struct_sym = "cfish_Obj";
+            vtable_var      = "CFISH_OBJ";
+        }
+        else if (strcmp(full_struct_sym, "lucy_VArray") == 0) {
+            full_struct_sym = "cfish_VArray";
+            vtable_var      = "CFISH_VARRAY";
+        }
+        else if (strcmp(full_struct_sym, "lucy_VTable") == 0) {
+            full_struct_sym = "cfish_VTable";
+            vtable_var      = "CFISH_VTABLE";
+        }
+
         start = CFCUtil_cat(start, full_struct_sym, "*\t", vtable_var, "_\n",
                             NULL);
         input = CFCUtil_cat(input, vtable_var, "_\n"

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/buildlib/Lucy/Build/Binding/Index.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Index.pm b/perl/buildlib/Lucy/Build/Binding/Index.pm
index 13e4fee..71913b1 100644
--- a/perl/buildlib/Lucy/Build/Binding/Index.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Index.pm
@@ -407,8 +407,8 @@ set_race_condition_debug1(val_sv)
     SV *val_sv;
 PPCODE:
     CFISH_DECREF(lucy_PolyReader_race_condition_debug1);
-    lucy_PolyReader_race_condition_debug1 = (lucy_CharBuf*)
-        XSBind_maybe_sv_to_cfish_obj(val_sv, LUCY_CHARBUF, NULL);
+    lucy_PolyReader_race_condition_debug1 = (cfish_CharBuf*)
+        XSBind_maybe_sv_to_cfish_obj(val_sv, CFISH_CHARBUF, NULL);
     if (lucy_PolyReader_race_condition_debug1) {
         (void)CFISH_INCREF(lucy_PolyReader_race_condition_debug1);
     }
@@ -584,7 +584,7 @@ PPCODE:
         }
     }
     else if (items == 1) {
-        CFISH_THROW(LUCY_ERR, "Missing required argument 'doc'");
+        CFISH_THROW(CFISH_ERR, "Missing required argument 'doc'");
     }
 
     // Either get a Doc or use the stock doc.
@@ -602,8 +602,8 @@ PPCODE:
         }
     }
     if (!doc) {
-        THROW(LUCY_ERR, "Need either a hashref or a %o",
-              Lucy_VTable_Get_Name(LUCY_DOC));
+        THROW(CFISH_ERR, "Need either a hashref or a %o",
+              Cfish_VTable_Get_Name(LUCY_DOC));
     }
 
     Lucy_Indexer_Add_Doc(self, doc, boost);
@@ -1116,8 +1116,8 @@ CODE:
         CFISH_RETHROW(CFISH_INCREF(cfish_Err_get_error()));
     }
     {
-        lucy_Obj *blank = Lucy_SortCache_Make_Blank(self);
-        lucy_Obj *value = Lucy_SortCache_Value(self, ord, blank);
+        cfish_Obj *blank = Lucy_SortCache_Make_Blank(self);
+        cfish_Obj *value = Lucy_SortCache_Value(self, ord, blank);
         RETVAL = XSBind_cfish_to_perl(value);
         CFISH_DECREF(blank);
     }

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/buildlib/Lucy/Build/Binding/Misc.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Misc.pm b/perl/buildlib/Lucy/Build/Binding/Misc.pm
index 0fb31a8..0e25807 100644
--- a/perl/buildlib/Lucy/Build/Binding/Misc.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Misc.pm
@@ -46,7 +46,7 @@ to_clownfish(sv)
     SV *sv;
 CODE:
 {
-    lucy_Obj *obj = XSBind_perl_to_cfish(sv);
+    cfish_Obj *obj = XSBind_perl_to_cfish(sv);
     RETVAL = CFISH_OBJ_TO_SV_NOINC(obj);
 }
 OUTPUT: RETVAL
@@ -58,7 +58,7 @@ CODE:
 {
     if (sv_isobject(sv) && sv_derived_from(sv, "Clownfish::Obj")) {
         IV tmp = SvIV(SvRV(sv));
-        lucy_Obj* obj = INT2PTR(lucy_Obj*, tmp);
+        cfish_Obj* obj = INT2PTR(cfish_Obj*, tmp);
         RETVAL = XSBind_cfish_to_perl(obj);
     }
     else {
@@ -85,9 +85,9 @@ bool
 run_tests(package)
     char *package;
 CODE:
-    lucy_CharBuf *class_name = lucy_CB_newf("%s", package);
-    lucy_TestFormatter *formatter
-        = (lucy_TestFormatter*)lucy_TestFormatterTAP_new();
+    cfish_CharBuf *class_name = cfish_CB_newf("%s", package);
+    cfish_TestFormatter *formatter
+        = (cfish_TestFormatter*)cfish_TestFormatterTAP_new();
     bool result = lucy_Test_run_batch(class_name, formatter);
     CFISH_DECREF(class_name);
     CFISH_DECREF(formatter);
@@ -129,8 +129,8 @@ CODE:
 {
     void *address = Lucy_BBSortEx_Fetch(self);
     if (address) {
-        RETVAL = XSBind_cfish_to_perl(*(lucy_Obj**)address);
-        CFISH_DECREF(*(lucy_Obj**)address);
+        RETVAL = XSBind_cfish_to_perl(*(cfish_Obj**)address);
+        CFISH_DECREF(*(cfish_Obj**)address);
     }
     else {
         RETVAL = newSV(0);
@@ -145,7 +145,7 @@ CODE:
 {
     void *address = Lucy_BBSortEx_Peek(self);
     if (address) {
-        RETVAL = XSBind_cfish_to_perl(*(lucy_Obj**)address);
+        RETVAL = XSBind_cfish_to_perl(*(cfish_Obj**)address);
     }
     else {
         RETVAL = newSV(0);
@@ -156,7 +156,7 @@ OUTPUT: RETVAL
 void
 feed(self, bb)
     lucy_BBSortEx *self;
-    lucy_ByteBuf *bb;
+    cfish_ByteBuf *bb;
 CODE:
     CFISH_INCREF(bb);
     Lucy_BBSortEx_Feed(self, &bb);

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/buildlib/Lucy/Build/Binding/Object.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Object.pm b/perl/buildlib/Lucy/Build/Binding/Object.pm
index ba9f957..0ba0bb6 100644
--- a/perl/buildlib/Lucy/Build/Binding/Object.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Object.pm
@@ -92,20 +92,20 @@ CODE:
 {
     STRLEN size;
     char *ptr = SvPV(sv, size);
-    lucy_ByteBuf *self = (lucy_ByteBuf*)XSBind_new_blank_obj(either_sv);
-    lucy_BB_init(self, size);
-    Lucy_BB_Mimic_Bytes(self, ptr, size);
+    cfish_ByteBuf *self = (cfish_ByteBuf*)XSBind_new_blank_obj(either_sv);
+    cfish_BB_init(self, size);
+    Cfish_BB_Mimic_Bytes(self, ptr, size);
     RETVAL = CFISH_OBJ_TO_SV_NOINC(self);
 }
 OUTPUT: RETVAL
 
 SV*
 _deserialize(self, instream)
-    lucy_ByteBuf *self;
+    cfish_ByteBuf *self;
     lucy_InStream *instream;
 CODE:
-    lucy_ByteBuf *thawed = Lucy_BB_Deserialize(self, instream);
-    RETVAL = (SV*)Lucy_BB_To_Host(thawed);
+    cfish_ByteBuf *thawed = Cfish_BB_Deserialize(self, instream);
+    RETVAL = (SV*)Cfish_BB_To_Host(thawed);
 OUTPUT: RETVAL
 END_XS_CODE
 
@@ -131,32 +131,32 @@ CODE:
 {
     STRLEN size;
     char *ptr = SvPVutf8(sv, size);
-    lucy_CharBuf *self = (lucy_CharBuf*)XSBind_new_blank_obj(either_sv);
-    lucy_CB_init(self, size);
-    Lucy_CB_Cat_Trusted_Str(self, ptr, size);
+    cfish_CharBuf *self = (cfish_CharBuf*)XSBind_new_blank_obj(either_sv);
+    cfish_CB_init(self, size);
+    Cfish_CB_Cat_Trusted_Str(self, ptr, size);
     RETVAL = CFISH_OBJ_TO_SV_NOINC(self);
 }
 OUTPUT: RETVAL
 
 SV*
 _clone(self)
-    lucy_CharBuf *self;
+    cfish_CharBuf *self;
 CODE:
-    RETVAL = CFISH_OBJ_TO_SV_NOINC(lucy_CB_clone(self));
+    RETVAL = CFISH_OBJ_TO_SV_NOINC(cfish_CB_clone(self));
 OUTPUT: RETVAL
 
 SV*
 _deserialize(self, instream)
-    lucy_CharBuf *self;
+    cfish_CharBuf *self;
     lucy_InStream *instream;
 CODE:
-    lucy_CharBuf *thawed = Lucy_CB_Deserialize(self, instream);
-    RETVAL = (SV*)Lucy_CB_To_Host(thawed);
+    cfish_CharBuf *thawed = Cfish_CB_Deserialize(self, instream);
+    RETVAL = (SV*)Cfish_CB_To_Host(thawed);
 OUTPUT: RETVAL
 
 SV*
 to_perl(self)
-    lucy_CharBuf *self;
+    cfish_CharBuf *self;
 CODE:
     RETVAL = XSBind_cb_to_sv(self);
 OUTPUT: RETVAL
@@ -171,8 +171,8 @@ CODE:
 {
     STRLEN size;
     char *ptr = SvPVutf8(sv, size);
-    lucy_ViewCharBuf *self
-        = lucy_ViewCB_new_from_trusted_utf8(ptr, size);
+    cfish_ViewCharBuf *self
+        = cfish_ViewCB_new_from_trusted_utf8(ptr, size);
     CHY_UNUSED_VAR(unused);
     RETVAL = CFISH_OBJ_TO_SV_NOINC(self);
 }
@@ -249,43 +249,43 @@ MODULE =  Lucy    PACKAGE = Clownfish::Hash
 
 SV*
 _deserialize(self, instream)
-    lucy_Hash *self;
+    cfish_Hash *self;
     lucy_InStream *instream;
 CODE:
-    lucy_Hash *thawed = Lucy_Hash_Deserialize(self, instream);
-    RETVAL = (SV*)Lucy_Hash_To_Host(thawed);
+    cfish_Hash *thawed = Cfish_Hash_Deserialize(self, instream);
+    RETVAL = (SV*)Cfish_Hash_To_Host(thawed);
 OUTPUT: RETVAL
 
 SV*
 _fetch(self, key)
-    lucy_Hash *self;
-    const lucy_CharBuf *key;
+    cfish_Hash *self;
+    const cfish_CharBuf *key;
 CODE:
-    RETVAL = CFISH_OBJ_TO_SV(lucy_Hash_fetch(self, (lucy_Obj*)key));
+    RETVAL = CFISH_OBJ_TO_SV(cfish_Hash_fetch(self, (cfish_Obj*)key));
 OUTPUT: RETVAL
 
 void
 store(self, key, value);
-    lucy_Hash          *self;
-    const lucy_CharBuf *key;
-    lucy_Obj           *value;
+    cfish_Hash          *self;
+    const cfish_CharBuf *key;
+    cfish_Obj           *value;
 PPCODE:
 {
     if (value) { CFISH_INCREF(value); }
-    lucy_Hash_store(self, (lucy_Obj*)key, value);
+    cfish_Hash_store(self, (cfish_Obj*)key, value);
 }
 
 void
 next(self)
-    lucy_Hash *self;
+    cfish_Hash *self;
 PPCODE:
 {
-    lucy_Obj *key;
-    lucy_Obj *val;
+    cfish_Obj *key;
+    cfish_Obj *val;
 
-    if (Lucy_Hash_Next(self, &key, &val)) {
-        SV *key_sv = (SV*)Lucy_Obj_To_Host(key);
-        SV *val_sv = (SV*)Lucy_Obj_To_Host(val);
+    if (Cfish_Hash_Next(self, &key, &val)) {
+        SV *key_sv = (SV*)Cfish_Obj_To_Host(key);
+        SV *val_sv = (SV*)Cfish_Obj_To_Host(val);
 
         XPUSHs(sv_2mortal(key_sv));
         XPUSHs(sv_2mortal(val_sv));
@@ -346,7 +346,7 @@ CODE:
         lucy_I32Arr_init(self, ints, size);
     }
     else {
-        THROW(LUCY_ERR, "Required param 'ints' isn't an arrayref");
+        THROW(CFISH_ERR, "Required param 'ints' isn't an arrayref");
     }
 
     RETVAL = CFISH_OBJ_TO_SV_NOINC(self);
@@ -401,8 +401,8 @@ new(either_sv, value)
     float  value;
 CODE:
 {
-    lucy_Float32 *self = (lucy_Float32*)XSBind_new_blank_obj(either_sv);
-    lucy_Float32_init(self, value);
+    cfish_Float32 *self = (cfish_Float32*)XSBind_new_blank_obj(either_sv);
+    cfish_Float32_init(self, value);
     RETVAL = CFISH_OBJ_TO_SV_NOINC(self);
 }
 OUTPUT: RETVAL
@@ -428,8 +428,8 @@ new(either_sv, value)
     double  value;
 CODE:
 {
-    lucy_Float64 *self = (lucy_Float64*)XSBind_new_blank_obj(either_sv);
-    lucy_Float64_init(self, value);
+    cfish_Float64 *self = (cfish_Float64*)XSBind_new_blank_obj(either_sv);
+    cfish_Float64_init(self, value);
     RETVAL = CFISH_OBJ_TO_SV_NOINC(self);
 }
 OUTPUT: RETVAL
@@ -550,29 +550,29 @@ MODULE = Lucy     PACKAGE = Clownfish::Obj
 
 bool
 is_a(self, class_name)
-    lucy_Obj *self;
-    const lucy_CharBuf *class_name;
+    cfish_Obj *self;
+    const cfish_CharBuf *class_name;
 CODE:
 {
-    lucy_VTable *target = lucy_VTable_fetch_vtable(class_name);
-    RETVAL = Lucy_Obj_Is_A(self, target);
+    cfish_VTable *target = cfish_VTable_fetch_vtable(class_name);
+    RETVAL = Cfish_Obj_Is_A(self, target);
 }
 OUTPUT: RETVAL
 
 void
 STORABLE_freeze(self, ...)
-    lucy_Obj *self;
+    cfish_Obj *self;
 PPCODE:
 {
     CHY_UNUSED_VAR(self);
     if (items < 2 || !SvTRUE(ST(1))) {
         SV *retval;
-        lucy_ByteBuf *serialized_bb;
+        cfish_ByteBuf *serialized_bb;
         lucy_RAMFileHandle *file_handle
             = lucy_RAMFH_open(NULL, LUCY_FH_WRITE_ONLY | LUCY_FH_CREATE, NULL);
-        lucy_OutStream *target = lucy_OutStream_open((lucy_Obj*)file_handle);
+        lucy_OutStream *target = lucy_OutStream_open((cfish_Obj*)file_handle);
 
-        Lucy_Obj_Serialize(self, target);
+        Cfish_Obj_Serialize(self, target);
 
         Lucy_OutStream_Close(target);
         serialized_bb
@@ -582,7 +582,7 @@ PPCODE:
         CFISH_DECREF(target);
 
         if (SvCUR(retval) == 0) { // Thwart Storable bug
-            THROW(LUCY_ERR, "Calling serialize produced an empty string");
+            THROW(CFISH_ERR, "Calling serialize produced an empty string");
         }
         ST(0) = sv_2mortal(retval);
         XSRETURN(1);
@@ -606,19 +606,19 @@ STORABLE_thaw(blank_obj, cloning, serialized_sv)
 PPCODE:
 {
     char *class_name = HvNAME(SvSTASH(SvRV(blank_obj)));
-    lucy_ZombieCharBuf *klass
+    cfish_ZombieCharBuf *klass
         = CFISH_ZCB_WRAP_STR(class_name, strlen(class_name));
-    lucy_VTable *vtable
-        = (lucy_VTable*)lucy_VTable_singleton((lucy_CharBuf*)klass, NULL);
+    cfish_VTable *vtable
+        = (cfish_VTable*)cfish_VTable_singleton((cfish_CharBuf*)klass, NULL);
     STRLEN len;
     char *ptr = SvPV(serialized_sv, len);
-    lucy_ViewByteBuf *contents = lucy_ViewBB_new(ptr, len);
-    lucy_RAMFile *ram_file = lucy_RAMFile_new((lucy_ByteBuf*)contents, true);
+    cfish_ViewByteBuf *contents = cfish_ViewBB_new(ptr, len);
+    lucy_RAMFile *ram_file = lucy_RAMFile_new((cfish_ByteBuf*)contents, true);
     lucy_RAMFileHandle *file_handle
         = lucy_RAMFH_open(NULL, LUCY_FH_READ_ONLY, ram_file);
-    lucy_InStream *instream = lucy_InStream_open((lucy_Obj*)file_handle);
-    lucy_Obj *self = Lucy_VTable_Foster_Obj(vtable, blank_obj);
-    lucy_Obj *deserialized = Lucy_Obj_Deserialize(self, instream);
+    lucy_InStream *instream = lucy_InStream_open((cfish_Obj*)file_handle);
+    cfish_Obj *self = Cfish_VTable_Foster_Obj(vtable, blank_obj);
+    cfish_Obj *deserialized = Cfish_Obj_Deserialize(self, instream);
 
     CHY_UNUSED_VAR(cloning);
     CFISH_DECREF(contents);
@@ -628,7 +628,7 @@ PPCODE:
 
     // Catch bad deserialize() override.
     if (deserialized != self) {
-        THROW(LUCY_ERR, "Error when deserializing obj of class %o", klass);
+        THROW(CFISH_ERR, "Error when deserializing obj of class %o", klass);
     }
 }
 END_XS_CODE
@@ -660,66 +660,66 @@ MODULE = Lucy   PACKAGE = Clownfish::VArray
 
 SV*
 shallow_copy(self)
-    lucy_VArray *self;
+    cfish_VArray *self;
 CODE:
-    RETVAL = CFISH_OBJ_TO_SV_NOINC(Lucy_VA_Shallow_Copy(self));
+    RETVAL = CFISH_OBJ_TO_SV_NOINC(Cfish_VA_Shallow_Copy(self));
 OUTPUT: RETVAL
 
 SV*
 _deserialize(self, instream)
-    lucy_VArray *self;
+    cfish_VArray *self;
     lucy_InStream *instream;
 CODE:
-    lucy_VArray *thawed = Lucy_VA_Deserialize(self, instream);
-    RETVAL = (SV*)Lucy_VA_To_Host(thawed);
+    cfish_VArray *thawed = Cfish_VA_Deserialize(self, instream);
+    RETVAL = (SV*)Cfish_VA_To_Host(thawed);
 OUTPUT: RETVAL
 
 SV*
 _clone(self)
-    lucy_VArray *self;
+    cfish_VArray *self;
 CODE:
-    RETVAL = CFISH_OBJ_TO_SV_NOINC(Lucy_VA_Clone(self));
+    RETVAL = CFISH_OBJ_TO_SV_NOINC(Cfish_VA_Clone(self));
 OUTPUT: RETVAL
 
 SV*
 shift(self)
-    lucy_VArray *self;
+    cfish_VArray *self;
 CODE:
-    RETVAL = CFISH_OBJ_TO_SV_NOINC(Lucy_VA_Shift(self));
+    RETVAL = CFISH_OBJ_TO_SV_NOINC(Cfish_VA_Shift(self));
 OUTPUT: RETVAL
 
 SV*
 pop(self)
-    lucy_VArray *self;
+    cfish_VArray *self;
 CODE:
-    RETVAL = CFISH_OBJ_TO_SV_NOINC(Lucy_VA_Pop(self));
+    RETVAL = CFISH_OBJ_TO_SV_NOINC(Cfish_VA_Pop(self));
 OUTPUT: RETVAL
 
 SV*
 delete(self, tick)
-    lucy_VArray *self;
+    cfish_VArray *self;
     uint32_t    tick;
 CODE:
-    RETVAL = CFISH_OBJ_TO_SV_NOINC(Lucy_VA_Delete(self, tick));
+    RETVAL = CFISH_OBJ_TO_SV_NOINC(Cfish_VA_Delete(self, tick));
 OUTPUT: RETVAL
 
 void
 store(self, tick, value);
-    lucy_VArray *self;
+    cfish_VArray *self;
     uint32_t     tick;
-    lucy_Obj    *value;
+    cfish_Obj    *value;
 PPCODE:
 {
     if (value) { CFISH_INCREF(value); }
-    lucy_VA_store(self, tick, value);
+    cfish_VA_store(self, tick, value);
 }
 
 SV*
 fetch(self, tick)
-    lucy_VArray *self;
+    cfish_VArray *self;
     uint32_t     tick;
 CODE:
-    RETVAL = CFISH_OBJ_TO_SV(Lucy_VA_Fetch(self, tick));
+    RETVAL = CFISH_OBJ_TO_SV(Cfish_VA_Fetch(self, tick));
 OUTPUT: RETVAL
 END_XS_CODE
 
@@ -742,10 +742,10 @@ MODULE = Lucy   PACKAGE = Clownfish::VTable
 SV*
 _get_registry()
 CODE:
-    if (lucy_VTable_registry == NULL) {
-        lucy_VTable_init_registry();
+    if (cfish_VTable_registry == NULL) {
+        cfish_VTable_init_registry();
     }
-    RETVAL = (SV*)Lucy_Obj_To_Host((lucy_Obj*)lucy_VTable_registry);
+    RETVAL = (SV*)Cfish_Obj_To_Host((cfish_Obj*)cfish_VTable_registry);
 OUTPUT: RETVAL
 
 SV*
@@ -754,28 +754,28 @@ singleton(unused_sv, ...)
 CODE:
 {
     CHY_UNUSED_VAR(unused_sv);
-    lucy_CharBuf *class_name = NULL;
-    lucy_VTable  *parent     = NULL;
+    cfish_CharBuf *class_name = NULL;
+    cfish_VTable  *parent     = NULL;
     bool args_ok
         = XSBind_allot_params(&(ST(0)), 1, items,
                               ALLOT_OBJ(&class_name, "class_name", 10, true,
-                                        LUCY_CHARBUF, alloca(cfish_ZCB_size())),
+                                        CFISH_CHARBUF, alloca(cfish_ZCB_size())),
                               ALLOT_OBJ(&parent, "parent", 6, false,
-                                        LUCY_VTABLE, NULL),
+                                        CFISH_VTABLE, NULL),
                               NULL);
     if (!args_ok) {
         CFISH_RETHROW(CFISH_INCREF(cfish_Err_get_error()));
     }
-    lucy_VTable *singleton = lucy_VTable_singleton(class_name, parent);
-    RETVAL = (SV*)Lucy_VTable_To_Host(singleton);
+    cfish_VTable *singleton = cfish_VTable_singleton(class_name, parent);
+    RETVAL = (SV*)Cfish_VTable_To_Host(singleton);
 }
 OUTPUT: RETVAL
 
 SV*
 make_obj(self)
-    lucy_VTable *self;
+    cfish_VTable *self;
 CODE:
-    lucy_Obj *blank = Lucy_VTable_Make_Obj(self);
+    cfish_Obj *blank = Cfish_VTable_Make_Obj(self);
     RETVAL = CFISH_OBJ_TO_SV_NOINC(blank);
 OUTPUT: RETVAL
 END_XS_CODE

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/buildlib/Lucy/Build/Binding/Search.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Search.pm b/perl/buildlib/Lucy/Build/Binding/Search.pm
index 51d6193..af63475 100644
--- a/perl/buildlib/Lucy/Build/Binding/Search.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Search.pm
@@ -513,7 +513,7 @@ CODE:
         CFISH_RETHROW(CFISH_INCREF(cfish_Err_get_error()));
     }
     const char *type_str = SvPVutf8_nolen(type_sv);
-    lucy_Obj *value = NULL;
+    cfish_Obj *value = NULL;
     uint32_t type = 0;
 
     if (strcmp(type_str, "OPEN_PAREN") == 0) {
@@ -539,11 +539,11 @@ CODE:
     }
     else if (strcmp(type_str, "FIELD") == 0) {
         type = LUCY_QPARSER_TOKEN_FIELD; 
-        value = CFISH_CERTIFY(XSBind_perl_to_cfish(value_sv), LUCY_CHARBUF);
+        value = CFISH_CERTIFY(XSBind_perl_to_cfish(value_sv), CFISH_CHARBUF);
     }
     else if (strcmp(type_str, "STRING") == 0) {
         type = LUCY_QPARSER_TOKEN_STRING; 
-        value = CFISH_CERTIFY(XSBind_perl_to_cfish(value_sv), LUCY_CHARBUF);
+        value = CFISH_CERTIFY(XSBind_perl_to_cfish(value_sv), CFISH_CHARBUF);
     }
     else if (strcmp(type_str, "QUERY") == 0) {
         type = LUCY_QPARSER_TOKEN_QUERY; 

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/buildlib/Lucy/Build/Binding/Util.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Util.pm b/perl/buildlib/Lucy/Build/Binding/Util.pm
index 237e93d..45b9ab4 100644
--- a/perl/buildlib/Lucy/Build/Binding/Util.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Util.pm
@@ -116,7 +116,7 @@ MODULE = Lucy   PACKAGE = Lucy::Util::IndexFileNames
 
 uint64_t
 extract_gen(name)
-    const lucy_CharBuf *name;
+    const cfish_CharBuf *name;
 CODE:
     RETVAL = lucy_IxFileNames_extract_gen(name);
 OUTPUT: RETVAL
@@ -126,7 +126,7 @@ latest_snapshot(folder)
     lucy_Folder *folder;
 CODE:
 {
-    lucy_CharBuf *latest = lucy_IxFileNames_latest_snapshot(folder);
+    cfish_CharBuf *latest = lucy_IxFileNames_latest_snapshot(folder);
     RETVAL = XSBind_cb_to_sv(latest);
     CFISH_DECREF(latest);
 }
@@ -222,7 +222,7 @@ to_base36(num)
 CODE:
 {
     char base36[cfish_StrHelp_MAX_BASE36_BYTES];
-    size_t size = lucy_StrHelp_to_base36(num, &base36);
+    size_t size = cfish_StrHelp_to_base36(num, &base36);
     RETVAL = newSVpvn(base36, size);
 }
 OUTPUT: RETVAL
@@ -254,7 +254,7 @@ CODE:
 {
     STRLEN len;
     char *ptr = SvPV(sv, len);
-    RETVAL = lucy_StrHelp_utf8_valid(ptr, len);
+    RETVAL = cfish_StrHelp_utf8_valid(ptr, len);
 }
 OUTPUT: RETVAL
 
@@ -274,7 +274,7 @@ PPCODE:
 {
     STRLEN len;
     char *ptr = SvPV(catted, len);
-    if (SvUTF8(sv)) { CFISH_THROW(LUCY_ERR, "Can't cat_bytes onto a UTF-8 SV"); }
+    if (SvUTF8(sv)) { CFISH_THROW(CFISH_ERR, "Can't cat_bytes onto a UTF-8 SV"); }
     sv_catpvn(sv, ptr, len);
 }
 END_XS_CODE

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/xs/Lucy/Analysis/RegexTokenizer.c
----------------------------------------------------------------------
diff --git a/perl/xs/Lucy/Analysis/RegexTokenizer.c b/perl/xs/Lucy/Analysis/RegexTokenizer.c
index 211e461..d175b59 100644
--- a/perl/xs/Lucy/Analysis/RegexTokenizer.c
+++ b/perl/xs/Lucy/Analysis/RegexTokenizer.c
@@ -40,20 +40,20 @@ lucy_RegexTokenizer_is_available(void) {
 
 lucy_RegexTokenizer*
 lucy_RegexTokenizer_init(lucy_RegexTokenizer *self,
-                         const lucy_CharBuf *pattern) {
+                         const cfish_CharBuf *pattern) {
     lucy_Analyzer_init((lucy_Analyzer*)self);
     #define DEFAULT_PATTERN "\\w+(?:['\\x{2019}]\\w+)*"
     if (pattern) {
-        if (Lucy_CB_Find_Str(pattern, "\\p", 2) != -1
-            || Lucy_CB_Find_Str(pattern, "\\P", 2) != -1
+        if (Cfish_CB_Find_Str(pattern, "\\p", 2) != -1
+            || Cfish_CB_Find_Str(pattern, "\\P", 2) != -1
            ) {
             CFISH_DECREF(self);
-            THROW(LUCY_ERR, "\\p and \\P constructs forbidden");
+            THROW(CFISH_ERR, "\\p and \\P constructs forbidden");
         }
-        self->pattern = Lucy_CB_Clone(pattern);
+        self->pattern = Cfish_CB_Clone(pattern);
     }
     else {
-        self->pattern = lucy_CB_new_from_trusted_utf8(
+        self->pattern = cfish_CB_new_from_trusted_utf8(
                             DEFAULT_PATTERN, sizeof(DEFAULT_PATTERN) - 1);
     }
 
@@ -94,12 +94,12 @@ S_set_token_re_but_not_pattern(lucy_RegexTokenizer *self, void *token_re) {
         magic = mg_find((SV*)token_re, PERL_MAGIC_qr);
     }
     if (!magic) {
-        THROW(LUCY_ERR, "token_re is not a qr// entity");
+        THROW(CFISH_ERR, "token_re is not a qr// entity");
     }
     REGEXP *rx = (REGEXP*)magic->mg_obj;
 #endif
     if (rx == NULL) {
-        THROW(LUCY_ERR, "Failed to extract REGEXP from token_re '%s'",
+        THROW(CFISH_ERR, "Failed to extract REGEXP from token_re '%s'",
               SvPV_nolen((SV*)token_re));
     }
     if (self->token_re) { ReREFCNT_dec(((REGEXP*)self->token_re)); }
@@ -112,7 +112,7 @@ S_set_pattern_from_token_re(lucy_RegexTokenizer *self, void *token_re) {
     SV *rv = newRV((SV*)token_re);
     STRLEN len = 0;
     char *ptr = SvPVutf8((SV*)rv, len);
-    Lucy_CB_Mimic_Str(self->pattern, ptr, len);
+    Cfish_CB_Mimic_Str(self->pattern, ptr, len);
     SvREFCNT_dec(rv);
 }
 
@@ -171,16 +171,16 @@ lucy_RegexTokenizer_tokenize_str(lucy_RegexTokenizer *self,
 
         // Get start and end offsets in Unicode code points.
         for (; string_arg < start_ptr; num_code_points++) {
-            string_arg += lucy_StrHelp_UTF8_COUNT[(uint8_t)(*string_arg)];
+            string_arg += cfish_StrHelp_UTF8_COUNT[(uint8_t)(*string_arg)];
             if (string_arg > string_end) {
-                THROW(LUCY_ERR, "scanned past end of '%s'", string_beg);
+                THROW(CFISH_ERR, "scanned past end of '%s'", string_beg);
             }
         }
         start = num_code_points;
         for (; string_arg < end_ptr; num_code_points++) {
-            string_arg += lucy_StrHelp_UTF8_COUNT[(uint8_t)(*string_arg)];
+            string_arg += cfish_StrHelp_UTF8_COUNT[(uint8_t)(*string_arg)];
             if (string_arg > string_end) {
-                THROW(LUCY_ERR, "scanned past end of '%s'", string_beg);
+                THROW(CFISH_ERR, "scanned past end of '%s'", string_beg);
             }
         }
         end = num_code_points;

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/xs/Lucy/Document/Doc.c
----------------------------------------------------------------------
diff --git a/perl/xs/Lucy/Document/Doc.c b/perl/xs/Lucy/Document/Doc.c
index aa3e4df..c20c2b0 100644
--- a/perl/xs/Lucy/Document/Doc.c
+++ b/perl/xs/Lucy/Document/Doc.c
@@ -25,7 +25,7 @@ lucy_Doc*
 lucy_Doc_init(lucy_Doc *self, void *fields, int32_t doc_id) {
     // Assign.
     if (fields) {
-        if (SvTYPE((SV*)fields) != SVt_PVHV) { THROW(LUCY_ERR, "Not a hash"); }
+        if (SvTYPE((SV*)fields) != SVt_PVHV) { THROW(CFISH_ERR, "Not a hash"); }
         self->fields = SvREFCNT_inc((SV*)fields);
     }
     else {
@@ -48,15 +48,15 @@ lucy_Doc_get_size(lucy_Doc *self) {
 }
 
 void
-lucy_Doc_store(lucy_Doc *self, const lucy_CharBuf *field, lucy_Obj *value) {
-    char   *key      = (char*)Lucy_CB_Get_Ptr8(field);
-    size_t  key_size = Lucy_CB_Get_Size(field);
+lucy_Doc_store(lucy_Doc *self, const cfish_CharBuf *field, cfish_Obj *value) {
+    char   *key      = (char*)Cfish_CB_Get_Ptr8(field);
+    size_t  key_size = Cfish_CB_Get_Size(field);
     SV *key_sv = newSVpvn(key, key_size);
     SV *val_sv = value == NULL
                  ? newSV(0)
-                 : Lucy_Obj_Is_A(value, LUCY_CHARBUF)
-                 ? XSBind_cb_to_sv((lucy_CharBuf*)value)
-                 : (SV*)Lucy_Obj_To_Host(value);
+                 : Cfish_Obj_Is_A(value, CFISH_CHARBUF)
+                 ? XSBind_cb_to_sv((cfish_CharBuf*)value)
+                 : (SV*)Cfish_Obj_To_Host(value);
     SvUTF8_on(key_sv);
     (void)hv_store_ent((HV*)self->fields, key_sv, val_sv, 0);
     // TODO: make this a thread-local instead of creating it every time?
@@ -135,24 +135,24 @@ lucy_Doc_deserialize(lucy_Doc *self, lucy_InStream *instream) {
     return self;
 }
 
-lucy_Obj*
-lucy_Doc_extract(lucy_Doc *self, lucy_CharBuf *field,
-                 lucy_ViewCharBuf *target) {
-    lucy_Obj *retval = NULL;
-    SV **sv_ptr = hv_fetch((HV*)self->fields, (char*)Lucy_CB_Get_Ptr8(field),
-                           Lucy_CB_Get_Size(field), 0);
+cfish_Obj*
+lucy_Doc_extract(lucy_Doc *self, cfish_CharBuf *field,
+                 cfish_ViewCharBuf *target) {
+    cfish_Obj *retval = NULL;
+    SV **sv_ptr = hv_fetch((HV*)self->fields, (char*)Cfish_CB_Get_Ptr8(field),
+                           Cfish_CB_Get_Size(field), 0);
 
     if (sv_ptr && XSBind_sv_defined(*sv_ptr)) {
         SV *const sv = *sv_ptr;
         if (sv_isobject(sv) && sv_derived_from(sv, "Clownfish::Obj")) {
             IV tmp = SvIV(SvRV(sv));
-            retval = INT2PTR(lucy_Obj*, tmp);
+            retval = INT2PTR(cfish_Obj*, tmp);
         }
         else {
             STRLEN size;
             char *ptr = SvPVutf8(sv, size);
-            Lucy_ViewCB_Assign_Str(target, ptr, size);
-            retval = (lucy_Obj*)target;
+            Cfish_ViewCB_Assign_Str(target, ptr, size);
+            retval = (cfish_Obj*)target;
         }
     }
 
@@ -168,36 +168,36 @@ lucy_Doc_to_host(lucy_Doc *self) {
     return perl_obj;
 }
 
-lucy_Hash*
+cfish_Hash*
 lucy_Doc_dump(lucy_Doc *self) {
-    lucy_Hash *dump = lucy_Hash_new(0);
-    Lucy_Hash_Store_Str(dump, "_class", 6,
-                        (lucy_Obj*)Lucy_CB_Clone(Lucy_Doc_Get_Class_Name(self)));
-    Lucy_Hash_Store_Str(dump, "doc_id", 7,
-                        (lucy_Obj*)lucy_CB_newf("%i32", self->doc_id));
-    Lucy_Hash_Store_Str(dump, "fields", 6,
+    cfish_Hash *dump = cfish_Hash_new(0);
+    Cfish_Hash_Store_Str(dump, "_class", 6,
+                        (cfish_Obj*)Cfish_CB_Clone(Lucy_Doc_Get_Class_Name(self)));
+    Cfish_Hash_Store_Str(dump, "doc_id", 7,
+                        (cfish_Obj*)cfish_CB_newf("%i32", self->doc_id));
+    Cfish_Hash_Store_Str(dump, "fields", 6,
                         XSBind_perl_to_cfish((SV*)self->fields));
     return dump;
 }
 
 lucy_Doc*
-lucy_Doc_load(lucy_Doc *self, lucy_Obj *dump) {
-    lucy_Hash *source = (lucy_Hash*)CFISH_CERTIFY(dump, LUCY_HASH);
-    lucy_CharBuf *class_name = (lucy_CharBuf*)CFISH_CERTIFY(
-                                   Lucy_Hash_Fetch_Str(source, "_class", 6),
-                                   LUCY_CHARBUF);
-    lucy_VTable *vtable = lucy_VTable_singleton(class_name, NULL);
-    lucy_Doc *loaded = (lucy_Doc*)Lucy_VTable_Make_Obj(vtable);
-    lucy_Obj *doc_id = CFISH_CERTIFY(
-                           Lucy_Hash_Fetch_Str(source, "doc_id", 7),
-                           LUCY_OBJ);
-    lucy_Hash *fields = (lucy_Hash*)CFISH_CERTIFY(
-                            Lucy_Hash_Fetch_Str(source, "fields", 6),
-                            LUCY_HASH);
-    SV *fields_sv = XSBind_cfish_to_perl((lucy_Obj*)fields);
+lucy_Doc_load(lucy_Doc *self, cfish_Obj *dump) {
+    cfish_Hash *source = (cfish_Hash*)CFISH_CERTIFY(dump, CFISH_HASH);
+    cfish_CharBuf *class_name = (cfish_CharBuf*)CFISH_CERTIFY(
+                                   Cfish_Hash_Fetch_Str(source, "_class", 6),
+                                   CFISH_CHARBUF);
+    cfish_VTable *vtable = cfish_VTable_singleton(class_name, NULL);
+    lucy_Doc *loaded = (lucy_Doc*)Cfish_VTable_Make_Obj(vtable);
+    cfish_Obj *doc_id = CFISH_CERTIFY(
+                           Cfish_Hash_Fetch_Str(source, "doc_id", 7),
+                           CFISH_OBJ);
+    cfish_Hash *fields = (cfish_Hash*)CFISH_CERTIFY(
+                            Cfish_Hash_Fetch_Str(source, "fields", 6),
+                            CFISH_HASH);
+    SV *fields_sv = XSBind_cfish_to_perl((cfish_Obj*)fields);
     CHY_UNUSED_VAR(self);
 
-    loaded->doc_id = (int32_t)Lucy_Obj_To_I64(doc_id);
+    loaded->doc_id = (int32_t)Cfish_Obj_To_I64(doc_id);
     loaded->fields  = SvREFCNT_inc(SvRV(fields_sv));
     SvREFCNT_dec(fields_sv);
 
@@ -205,14 +205,14 @@ lucy_Doc_load(lucy_Doc *self, lucy_Obj *dump) {
 }
 
 bool
-lucy_Doc_equals(lucy_Doc *self, lucy_Obj *other) {
+lucy_Doc_equals(lucy_Doc *self, cfish_Obj *other) {
     lucy_Doc *twin = (lucy_Doc*)other;
     HV *my_fields;
     HV *other_fields;
     I32 num_fields;
 
     if (twin == self)                    { return true;  }
-    if (!Lucy_Obj_Is_A(other, LUCY_DOC)) { return false; }
+    if (!Cfish_Obj_Is_A(other, LUCY_DOC)) { return false; }
     if (!self->doc_id == twin->doc_id)   { return false; }
     if (!!self->fields ^ !!twin->fields) { return false; }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/xs/Lucy/Index/DocReader.c
----------------------------------------------------------------------
diff --git a/perl/xs/Lucy/Index/DocReader.c b/perl/xs/Lucy/Index/DocReader.c
index 6230e77..0c7b2ac 100644
--- a/perl/xs/Lucy/Index/DocReader.c
+++ b/perl/xs/Lucy/Index/DocReader.c
@@ -60,10 +60,10 @@ lucy_DefDocReader_fetch_doc(lucy_DefaultDocReader *self, int32_t doc_id) {
         *SvEND(field_name_sv) = '\0';
 
         // Find the Field's FieldType.
-        lucy_ZombieCharBuf *field_name_zcb
+        cfish_ZombieCharBuf *field_name_zcb
             = CFISH_ZCB_WRAP_STR(field_name_ptr, field_name_len);
-        Lucy_ZCB_Assign_Str(field_name_zcb, field_name_ptr, field_name_len);
-        type = Lucy_Schema_Fetch_Type(schema, (lucy_CharBuf*)field_name_zcb);
+        Cfish_ZCB_Assign_Str(field_name_zcb, field_name_ptr, field_name_len);
+        type = Lucy_Schema_Fetch_Type(schema, (cfish_CharBuf*)field_name_zcb);
 
         // Read the field value.
         switch (Lucy_FType_Primitive_ID(type) & lucy_FType_PRIMITIVE_ID_MASK) {
@@ -107,7 +107,7 @@ lucy_DefDocReader_fetch_doc(lucy_DefaultDocReader *self, int32_t doc_id) {
                 break;
             default:
                 value_sv = NULL;
-                CFISH_THROW(LUCY_ERR, "Unrecognized type: %o", type);
+                CFISH_THROW(CFISH_ERR, "Unrecognized type: %o", type);
         }
 
         // Store the value.

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/xs/Lucy/Index/Inverter.c
----------------------------------------------------------------------
diff --git a/perl/xs/Lucy/Index/Inverter.c b/perl/xs/Lucy/Index/Inverter.c
index 0653501..7f0bc95 100644
--- a/perl/xs/Lucy/Index/Inverter.c
+++ b/perl/xs/Lucy/Index/Inverter.c
@@ -43,35 +43,35 @@ S_fetch_entry(lucy_Inverter *self, HE *hash_entry) {
     else {
         key = HeKEY(hash_entry);
         key_len = he_key_len;
-        if (!lucy_StrHelp_utf8_valid(key, key_len)) {
+        if (!cfish_StrHelp_utf8_valid(key, key_len)) {
             SV *key_sv = HeSVKEY_force(hash_entry);
             key = SvPVutf8(key_sv, key_len);
         }
     }
 
-    lucy_ZombieCharBuf *field = CFISH_ZCB_WRAP_STR(key, key_len);
+    cfish_ZombieCharBuf *field = CFISH_ZCB_WRAP_STR(key, key_len);
     int32_t field_num
-        = Lucy_Seg_Field_Num(self->segment, (lucy_CharBuf*)field);
+        = Lucy_Seg_Field_Num(self->segment, (cfish_CharBuf*)field);
     if (!field_num) {
         // This field seems not to be in the segment yet.  Try to find it in
         // the Schema.
-        if (Lucy_Schema_Fetch_Type(schema, (lucy_CharBuf*)field)) {
+        if (Lucy_Schema_Fetch_Type(schema, (cfish_CharBuf*)field)) {
             // The field is in the Schema.  Get a field num from the Segment.
             field_num = Lucy_Seg_Add_Field(self->segment,
-                                           (lucy_CharBuf*)field);
+                                           (cfish_CharBuf*)field);
         }
         else {
             // We've truly failed to find the field.  The user must
             // not have spec'd it.
-            THROW(LUCY_ERR, "Unknown field name: '%s'", key);
+            THROW(CFISH_ERR, "Unknown field name: '%s'", key);
         }
     }
 
     lucy_InverterEntry *entry
-        = (lucy_InverterEntry*)Lucy_VA_Fetch(self->entry_pool, field_num);
+        = (lucy_InverterEntry*)Cfish_VA_Fetch(self->entry_pool, field_num);
     if (!entry) {
-        entry = lucy_InvEntry_new(schema, (lucy_CharBuf*)field, field_num);
-        Lucy_VA_Store(self->entry_pool, field_num, (lucy_Obj*)entry);
+        entry = lucy_InvEntry_new(schema, (cfish_CharBuf*)field, field_num);
+        Cfish_VA_Store(self->entry_pool, field_num, (cfish_Obj*)entry);
     }
     return entry;
 }
@@ -96,44 +96,44 @@ lucy_Inverter_invert_doc(lucy_Inverter *self, lucy_Doc *doc) {
             case lucy_FType_TEXT: {
                     STRLEN val_len;
                     char *val_ptr = SvPVutf8(value_sv, val_len);
-                    lucy_ViewCharBuf *value
-                        = (lucy_ViewCharBuf*)inv_entry->value;
-                    Lucy_ViewCB_Assign_Str(value, val_ptr, val_len);
+                    cfish_ViewCharBuf *value
+                        = (cfish_ViewCharBuf*)inv_entry->value;
+                    Cfish_ViewCB_Assign_Str(value, val_ptr, val_len);
                     break;
                 }
             case lucy_FType_BLOB: {
                     STRLEN val_len;
                     char *val_ptr = SvPV(value_sv, val_len);
-                    lucy_ViewByteBuf *value
-                        = (lucy_ViewByteBuf*)inv_entry->value;
-                    Lucy_ViewBB_Assign_Bytes(value, val_ptr, val_len);
+                    cfish_ViewByteBuf *value
+                        = (cfish_ViewByteBuf*)inv_entry->value;
+                    Cfish_ViewBB_Assign_Bytes(value, val_ptr, val_len);
                     break;
                 }
             case lucy_FType_INT32: {
-                    lucy_Integer32* value = (lucy_Integer32*)inv_entry->value;
-                    Lucy_Int32_Set_Value(value, SvIV(value_sv));
+                    cfish_Integer32* value = (cfish_Integer32*)inv_entry->value;
+                    Cfish_Int32_Set_Value(value, SvIV(value_sv));
                     break;
                 }
             case lucy_FType_INT64: {
-                    lucy_Integer64* value = (lucy_Integer64*)inv_entry->value;
+                    cfish_Integer64* value = (cfish_Integer64*)inv_entry->value;
                     int64_t val = sizeof(IV) == 8
                                   ? SvIV(value_sv)
                                   : (int64_t)SvNV(value_sv); // lossy
-                    Lucy_Int64_Set_Value(value, val);
+                    Cfish_Int64_Set_Value(value, val);
                     break;
                 }
             case lucy_FType_FLOAT32: {
-                    lucy_Float32* value = (lucy_Float32*)inv_entry->value;
-                    Lucy_Float32_Set_Value(value, (float)SvNV(value_sv));
+                    cfish_Float32* value = (cfish_Float32*)inv_entry->value;
+                    Cfish_Float32_Set_Value(value, (float)SvNV(value_sv));
                     break;
                 }
             case lucy_FType_FLOAT64: {
-                    lucy_Float64* value = (lucy_Float64*)inv_entry->value;
-                    Lucy_Float64_Set_Value(value, SvNV(value_sv));
+                    cfish_Float64* value = (cfish_Float64*)inv_entry->value;
+                    Cfish_Float64_Set_Value(value, SvNV(value_sv));
                     break;
                 }
             default:
-                THROW(LUCY_ERR, "Unrecognized type: %o", type);
+                THROW(CFISH_ERR, "Unrecognized type: %o", type);
         }
 
         Lucy_Inverter_Add_Field(self, inv_entry);

http://git-wip-us.apache.org/repos/asf/lucy/blob/4d9f129c/perl/xs/XSBind.h
----------------------------------------------------------------------
diff --git a/perl/xs/XSBind.h b/perl/xs/XSBind.h
index 8d6e0ba..c5a5453 100644
--- a/perl/xs/XSBind.h
+++ b/perl/xs/XSBind.h
@@ -44,7 +44,7 @@ extern "C" {
 /** Given either a class name or a perl object, manufacture a new Clownfish
  * object suitable for supplying to a cfish_Foo_init() function.
  */
-LUCY_VISIBLE cfish_Obj*
+CFISH_VISIBLE cfish_Obj*
 cfish_XSBind_new_blank_obj(SV *either_sv);
 
 /** Test whether an SV is defined.  Handles "get" magic, unlike SvOK on its
@@ -64,13 +64,13 @@ cfish_XSBind_sv_defined(SV *sv) {
  * <code>allocation</code>, assign the SV's string to it, and return that
  * instead.  If all else fails, throw an exception.
  */
-LUCY_VISIBLE cfish_Obj*
+CFISH_VISIBLE cfish_Obj*
 cfish_XSBind_sv_to_cfish_obj(SV *sv, cfish_VTable *vtable, void *allocation);
 
 /** As XSBind_sv_to_cfish_obj above, but returns NULL instead of throwing an
  * exception.
  */
-LUCY_VISIBLE cfish_Obj*
+CFISH_VISIBLE cfish_Obj*
 cfish_XSBind_maybe_sv_to_cfish_obj(SV *sv, cfish_VTable *vtable,
                                    void *allocation);
 
@@ -116,24 +116,24 @@ cfish_XSBind_cfish_obj_to_sv_noinc(cfish_Obj *obj) {
  * SVs, ByteBufs to SVs, VArrays to Perl array refs, Hashes to Perl hashrefs,
  * and any other object to a Perl object wrapping the Clownfish Obj.
  */
-LUCY_VISIBLE SV*
+CFISH_VISIBLE SV*
 cfish_XSBind_cfish_to_perl(cfish_Obj *obj);
 
 /** Deep conversion of Perl data structures to Clownfish objects -- Perl hash
  * to Hash, Perl array to VArray, Clownfish objects stripped of their
  * wrappers, and everything else stringified and turned to a CharBuf.
  */
-LUCY_VISIBLE cfish_Obj*
+CFISH_VISIBLE cfish_Obj*
 cfish_XSBind_perl_to_cfish(SV *sv);
 
 /** Convert a ByteBuf into a new string SV.
  */
-LUCY_VISIBLE SV*
+CFISH_VISIBLE SV*
 cfish_XSBind_bb_to_sv(const cfish_ByteBuf *bb);
 
 /** Convert a CharBuf into a new UTF-8 string SV.
  */
-LUCY_VISIBLE SV*
+CFISH_VISIBLE SV*
 cfish_XSBind_cb_to_sv(const cfish_CharBuf *cb);
 
 /** Perl-specific wrapper for Err#trap.  The "routine" must be either a
@@ -144,15 +144,15 @@ cfish_XSBind_trap(SV *routine, SV *context);
 
 /** Turn on overloading for the supplied Perl object and its class.
  */
-LUCY_VISIBLE void
+CFISH_VISIBLE void
 cfish_XSBind_enable_overload(void *pobj);
 
 /** Process hash-style params passed to an XS subroutine.  The varargs must be
  * a NULL-terminated series of ALLOT_ macros.
  *
  *     cfish_XSBind_allot_params(stack, start, num_stack_elems,
- *          ALLOT_OBJ(&field, "field", 5, LUCY_CHARBUF, true, alloca(cfish_ZCB_size()),
- *          ALLOT_OBJ(&term, "term", 4, LUCY_CHARBUF, true, alloca(cfish_ZCB_size()),
+ *          ALLOT_OBJ(&field, "field", 5, CFISH_CHARBUF, true, alloca(cfish_ZCB_size()),
+ *          ALLOT_OBJ(&term, "term", 4, CFISH_CHARBUF, true, alloca(cfish_ZCB_size()),
  *          NULL);
  *
  * The following ALLOT_ macros are available for primitive types:
@@ -208,7 +208,7 @@ cfish_XSBind_enable_overload(void *pobj);
  * (generally, the XS variable "items").
  * @return true on success, false on failure (sets Err_error).
  */
-LUCY_VISIBLE bool
+CFISH_VISIBLE bool
 cfish_XSBind_allot_params(SV** stack, int32_t start,
                           int32_t num_stack_elems, ...);
 


[lucy-commits] [05/26] git commit: refs/heads/separate-clownfish-wip2 - Improve support for multiple parcels

Posted by nw...@apache.org.
Improve support for multiple parcels

* Generate separate parcel.h and parcel.c files for every parcel.
* Support multiple parcels in a single binary.
* Use intra-parcel dependency information for includes and
  bootstrapping.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/32fe546c
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/32fe546c
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/32fe546c

Branch: refs/heads/separate-clownfish-wip2
Commit: 32fe546c08429a9ed7cf6f9e92d19f155186d764
Parents: cbda25e
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue May 21 00:50:05 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:17 2013 +0200

----------------------------------------------------------------------
 c/install.sh                                       |    1 +
 clownfish/compiler/perl/lib/Clownfish/CFC.pm       |    5 +-
 clownfish/compiler/perl/lib/Clownfish/CFC.xs       |    7 +-
 .../compiler/perl/lib/Clownfish/CFC/Perl/Build.pm  |    7 +-
 clownfish/compiler/src/CFCBindAliases.c            |    1 -
 clownfish/compiler/src/CFCBindClass.c              |   13 +-
 clownfish/compiler/src/CFCBindCore.c               |  226 +++++++++------
 clownfish/compiler/src/CFCParcel.c                 |   16 +
 clownfish/compiler/src/CFCParcel.h                 |    5 +
 clownfish/compiler/src/CFCPerl.c                   |   98 +++----
 clownfish/compiler/src/CFCPerl.h                   |   11 +-
 common/charmonizer.c                               |    9 +
 common/charmonizer.main                            |    9 +
 core/Clownfish.c                                   |   27 ++
 core/Lucy.c                                        |    7 -
 perl/Build.PL                                      |    2 +-
 perl/buildlib/Lucy/Build/Binding/Misc.pm           |    2 +-
 17 files changed, 265 insertions(+), 181 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/c/install.sh
----------------------------------------------------------------------
diff --git a/c/install.sh b/c/install.sh
index 7a8495e..f0c9446 100755
--- a/c/install.sh
+++ b/c/install.sh
@@ -67,6 +67,7 @@ esac
 
 mkdir -p $prefix/include
 cp autogen/include/cfish_hostdefs.h $prefix/include
+cp autogen/include/cfish_parcel.h $prefix/include
 cp autogen/include/lucy_parcel.h $prefix/include
 cp -R autogen/include/Clownfish $prefix/include
 cp -R autogen/include/Lucy $prefix/include

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/perl/lib/Clownfish/CFC.pm
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC.pm b/clownfish/compiler/perl/lib/Clownfish/CFC.pm
index 6635096..cbd28ee 100644
--- a/clownfish/compiler/perl/lib/Clownfish/CFC.pm
+++ b/clownfish/compiler/perl/lib/Clownfish/CFC.pm
@@ -698,7 +698,6 @@ BEGIN { XSLoader::load( 'Clownfish::CFC', '0.01' ) }
     use Clownfish::CFC::Util qw( verify_args a_isa_b );
 
     our %new_PARAMS = (
-        parcel     => undef,
         hierarchy  => undef,
         lib_dir    => undef,
         boot_class => undef,
@@ -709,10 +708,8 @@ BEGIN { XSLoader::load( 'Clownfish::CFC', '0.01' ) }
     sub new {
         my ( $either, %args ) = @_;
         verify_args( \%new_PARAMS, %args ) or confess $@;
-        $args{parcel}
-            = Clownfish::CFC::Model::Parcel->acquire( $args{parcel} );
         return _new(
-            @args{qw( parcel hierarchy lib_dir boot_class header footer )} );
+            @args{qw( hierarchy lib_dir boot_class header footer )} );
     }
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC.xs b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
index 6d3f4f2..308c453 100644
--- a/clownfish/compiler/perl/lib/Clownfish/CFC.xs
+++ b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
@@ -1876,16 +1876,15 @@ PPCODE:
 MODULE = Clownfish   PACKAGE = Clownfish::CFC::Binding::Perl
 
 SV*
-_new(parcel, hierarchy, lib_dir, boot_class, header, footer)
-    CFCParcel *parcel;
+_new(hierarchy, lib_dir, boot_class, header, footer)
     CFCHierarchy *hierarchy;
     const char *lib_dir;
     const char *boot_class;
     const char *header;
     const char *footer;
 CODE:
-    CFCPerl *self = CFCPerl_new(parcel, hierarchy, lib_dir, boot_class,
-                                header, footer);
+    CFCPerl *self = CFCPerl_new(hierarchy, lib_dir, boot_class, header,
+                                footer);
     RETVAL = S_cfcbase_to_perlref(self);
     CFCBase_decref((CFCBase*)self);
 OUTPUT: RETVAL

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm b/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
index b816f1c..0243aad 100644
--- a/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
+++ b/clownfish/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
@@ -243,15 +243,10 @@ sub _compile_clownfish {
         $package_name->bind_all;
     }
 
-    my $module_name  = $self->module_name;
-    my @module_parts = split( '::', $module_name );
-    my $parcel       = $module_parts[-1];
-
     my $binding = Clownfish::CFC::Binding::Perl->new(
-        parcel     => $parcel,
         hierarchy  => $hierarchy,
         lib_dir    => $LIB_DIR,
-        boot_class => $module_name,
+        boot_class => $self->module_name,
         header     => $self->clownfish_params('autogen_header'),
         footer     => '',
     );

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/src/CFCBindAliases.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCBindAliases.c b/clownfish/compiler/src/CFCBindAliases.c
index 12890ad..91da364 100644
--- a/clownfish/compiler/src/CFCBindAliases.c
+++ b/clownfish/compiler/src/CFCBindAliases.c
@@ -24,7 +24,6 @@ struct alias {
 };
 
 struct alias aliases[] = {
-    {"CFISH_VISIBLE", "LUCY_VISIBLE"},
     {NULL, NULL}
 };
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/src/CFCBindClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCBindClass.c b/clownfish/compiler/src/CFCBindClass.c
index 9c4548a..9c15345 100644
--- a/clownfish/compiler/src/CFCBindClass.c
+++ b/clownfish/compiler/src/CFCBindClass.c
@@ -119,8 +119,7 @@ CFCBindClass_to_c_header(CFCBindClass *self) {
 
 static char*
 S_to_c_header_inert(CFCBindClass *self) {
-    //const char *prefix    = CFCClass_get_prefix(self->client);
-    const char *prefix    = "lucy_";
+    const char *prefix    = CFCClass_get_prefix(self->client);
     char *inert_func_decs = S_sub_declarations(self);
     char *inert_var_defs  = S_inert_var_declarations(self);
     char *short_names     = S_short_names(self);
@@ -156,10 +155,8 @@ static char*
 S_to_c_header_dynamic(CFCBindClass *self) {
     const char *privacy_symbol  = CFCClass_privacy_symbol(self->client);
     const char *vt_var          = CFCClass_full_vtable_var(self->client);
-    //const char *prefix          = CFCClass_get_prefix(self->client);
-    //const char *PREFIX          = CFCClass_get_PREFIX(self->client);
-    const char *prefix          = "lucy_";
-    const char *PREFIX          = "LUCY_";
+    const char *prefix          = CFCClass_get_prefix(self->client);
+    const char *PREFIX          = CFCClass_get_PREFIX(self->client);
     char *struct_def            = S_struct_definition(self);
     char *parent_include        = S_parent_include(self);
     char *sub_declarations      = S_sub_declarations(self);
@@ -168,8 +165,12 @@ S_to_c_header_dynamic(CFCBindClass *self) {
     char *method_defs           = S_method_defs(self);
     char *short_names           = S_short_names(self);
 
+    // We must include lucy_parcel.h for the Serialize/Deserialize methods.
+    // This should be removed when InStream and OutStream are moved to the
+    // Clownfish parcel or serialization is reworked.
     char pattern[] =
         "#include \"%sparcel.h\"\n"
+        "#include \"lucy_parcel.h\"\n" // For serialize/deserialize
         "\n"
         "/* Include the header for this class's parent. \n"
         " */\n"

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/src/CFCBindCore.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCBindCore.c b/clownfish/compiler/src/CFCBindCore.c
index ec36cab..c1f200e 100644
--- a/clownfish/compiler/src/CFCBindCore.c
+++ b/clownfish/compiler/src/CFCBindCore.c
@@ -22,7 +22,6 @@
 #define CFC_NEED_BASE_STRUCT_DEF
 #include "CFCBase.h"
 #include "CFCBindCore.h"
-#include "CFCBindAliases.h"
 #include "CFCBindClass.h"
 #include "CFCBindFile.h"
 #include "CFCClass.h"
@@ -45,12 +44,12 @@ struct CFCBindCore {
  * all classes, plus typedefs for all class structs.
  */
 static void
-S_write_parcel_h(CFCBindCore *self);
+S_write_parcel_h(CFCBindCore *self, CFCParcel *parcel);
 
 /* Write the "parcel.c" file containing autogenerated implementation code.
  */
 static void
-S_write_parcel_c(CFCBindCore *self);
+S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel);
 
 static char*
 S_charmony_defines();
@@ -116,8 +115,13 @@ CFCBindCore_write_all_modified(CFCBindCore *self, int modified) {
     // If any class definition has changed, rewrite the parcel.h and parcel.c
     // files.
     if (modified) {
-        S_write_parcel_h(self);
-        S_write_parcel_c(self);
+        CFCParcel **parcels = CFCParcel_source_parcels();
+        for (size_t i = 0; parcels[i]; ++i) {
+            CFCParcel *parcel = parcels[i];
+            S_write_parcel_h(self, parcel);
+            S_write_parcel_c(self, parcel);
+        }
+        FREEMEM(parcels);
     }
 
     return modified;
@@ -127,69 +131,41 @@ CFCBindCore_write_all_modified(CFCBindCore *self, int modified) {
  * all classes, plus typedefs for all class structs.
  */
 static void
-S_write_parcel_h(CFCBindCore *self) {
-    CFCHierarchy *hierarchy = self->hierarchy;
-    CFCParcel    *parcel    = NULL;
+S_write_parcel_h(CFCBindCore *self, CFCParcel *parcel) {
+    CFCHierarchy *hierarchy   = self->hierarchy;
+    const char   *prefix      = CFCParcel_get_prefix(parcel);
+    const char   *PREFIX      = CFCParcel_get_PREFIX(parcel);
+    const char   *privacy_sym = CFCParcel_get_privacy_sym(parcel);
 
     char *charmony_defines = S_charmony_defines();
 
     // Declare object structs for all instantiable classes.
-    // Obtain parcel prefix for use in bootstrap function name.
     char *typedefs = CFCUtil_strdup("");
     CFCClass **ordered = CFCHierarchy_ordered_classes(hierarchy);
     for (int i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
+        const char *class_prefix = CFCClass_get_prefix(klass);
+        if (strcmp(class_prefix, prefix) != 0) { continue; }
+
         if (!CFCClass_inert(klass)) {
             const char *full_struct = CFCClass_full_struct_sym(klass);
             typedefs = CFCUtil_cat(typedefs, "typedef struct ", full_struct,
                                    " ", full_struct, ";\n", NULL);
         }
-        if (!CFCClass_included(klass)) {
-            if (parcel && CFCClass_get_parcel(klass) != parcel) {
-                //CFCUtil_die("Multiple parcels not yet supported.");
-            }
-            parcel = CFCClass_get_parcel(klass);
-        }
     }
     FREEMEM(ordered);
 
-    if (!parcel) {
-        CFCUtil_die("No source classes found.");
-    }
-    //const char *prefix = CFCParcel_get_prefix(parcel);
-    //const char *PREFIX = CFCParcel_get_PREFIX(parcel);
-    const char *prefix = "lucy_";
-    const char *PREFIX = "LUCY_";
-
-    // Create Clownfish aliases if necessary.
-    char *aliases = CFCBindAliases_c_aliases();
-
-    const char pattern[] =
-        "%s\n"
-        "#ifndef CFCPARCEL_H\n"
-        "#define CFCPARCEL_H 1\n"
-        "\n"
-        "#ifdef __cplusplus\n"
-        "extern \"C\" {\n"
-        "#endif\n"
-        "\n"
+    // Special includes for Clownfish parcel.
+    const char *cfish_includes_pattern =
         "#include <stdarg.h>\n"
         "#include <stddef.h>\n"
         "\n"
         "%s"
         "\n"
-        "#include \"cfish_hostdefs.h\"\n"
-        "\n"
-        "#ifdef CFP_LUCY\n"
-        "  #include \"charmony.h\"\n"
-        "  #define LUCY_VISIBLE CFISH_EXPORT\n"
-        "#else\n"
-        "  #define LUCY_VISIBLE CFISH_IMPORT\n"
-        "#endif\n"
-        "\n"
-        "%s\n"
-        "%s\n"
-        "\n"
+        "#include \"cfish_hostdefs.h\"\n";
+
+    // Special definitions for Clownfish parcel.
+    const char *cfish_defs =
         "/* Generic method pointer.\n"
         " */\n"
         "typedef void\n"
@@ -269,6 +245,52 @@ S_write_parcel_h(CFCBindCore *self) {
         "  #define MethodSpec               cfish_MethodSpec\n"
         "  #define VTableSpec               cfish_VTableSpec\n"
         "#endif\n"
+        "\n";
+
+    const char *extra_defs;
+    char *extra_includes;
+    if (strcmp(prefix, "cfish_") == 0) {
+        extra_defs = cfish_defs;
+        extra_includes = CFCUtil_sprintf(cfish_includes_pattern,
+                                         charmony_defines);
+    }
+    else {
+        extra_defs = "";
+        extra_includes = CFCUtil_strdup("");
+
+        // Include parcel.h of dependent parcels.
+        CFCParcel **dep_parcels = CFCParcel_dependent_parcels(parcel);
+        for (size_t i = 0; dep_parcels[i]; ++i) {
+            const char *dep_prefix = CFCParcel_get_prefix(dep_parcels[i]);
+            extra_includes = CFCUtil_cat(extra_includes, "#include <",
+                                         dep_prefix, "parcel.h>\n", NULL);
+        }
+        FREEMEM(dep_parcels);
+    }
+
+    const char pattern[] =
+        "%s\n"
+        "#ifndef CFISH_%sPARCEL_H\n"
+        "#define CFISH_%sPARCEL_H 1\n"
+        "\n"
+        "#ifdef __cplusplus\n"
+        "extern \"C\" {\n"
+        "#endif\n"
+        "\n"
+        "%s" // Extra includes.
+        "\n"
+        "#ifdef %s\n"
+        "  #include \"charmony.h\"\n"
+        "  #define %sVISIBLE CFISH_EXPORT\n"
+        "#else\n"
+        "  #define %sVISIBLE CFISH_IMPORT\n"
+        "#endif\n"
+        "\n"
+        "%s" // Typedefs.
+        "\n"
+        "%s" // Extra definitions.
+        "%sVISIBLE void\n"
+        "%sbootstrap_inheritance();\n"
         "\n"
         "%sVISIBLE void\n"
         "%sbootstrap_parcel();\n"
@@ -280,13 +302,15 @@ S_write_parcel_h(CFCBindCore *self) {
         "}\n"
         "#endif\n"
         "\n"
-        "#endif /* CFCPARCEL_H */\n"
+        "#endif /* CFISH_%sPARCEL_H */\n"
         "\n"
         "%s\n"
         "\n";
     char *file_content
-        = CFCUtil_sprintf(pattern, self->header, charmony_defines, aliases,
-                          typedefs, PREFIX, prefix, prefix, self->footer);
+        = CFCUtil_sprintf(pattern, self->header, PREFIX, PREFIX,
+                          extra_includes, privacy_sym, PREFIX, PREFIX,
+                          typedefs, extra_defs, PREFIX, prefix, PREFIX, prefix,
+                          prefix, PREFIX, self->footer);
 
     // Unlink then write file.
     const char *inc_dest = CFCHierarchy_get_include_dest(hierarchy);
@@ -297,18 +321,17 @@ S_write_parcel_h(CFCBindCore *self) {
     FREEMEM(filepath);
 
     FREEMEM(charmony_defines);
-    FREEMEM(aliases);
     FREEMEM(typedefs);
+    FREEMEM(extra_includes);
     FREEMEM(file_content);
 }
 
 static void
-S_write_parcel_c(CFCBindCore *self) {
+S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
     CFCHierarchy *hierarchy = self->hierarchy;
-    CFCParcel    *parcel    = NULL;
+    const char   *prefix    = CFCParcel_get_prefix(parcel);
 
-    // Aggregate C code from all files.
-    // Obtain parcel prefix for use in bootstrap function name.
+    // Aggregate C code for the parcel.
     char *privacy_syms = CFCUtil_strdup("");
     char *includes     = CFCUtil_strdup("");
     char *c_data       = CFCUtil_strdup("");
@@ -318,13 +341,13 @@ S_write_parcel_c(CFCBindCore *self) {
     CFCClass **ordered  = CFCHierarchy_ordered_classes(hierarchy);
     for (int i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
+        const char *class_prefix = CFCClass_get_prefix(klass);
+        if (strcmp(class_prefix, prefix) != 0) { continue; }
 
         const char *include_h = CFCClass_include_h(klass);
         includes = CFCUtil_cat(includes, "#include \"", include_h,
                                "\"\n", NULL);
 
-        if (CFCClass_included(klass)) { continue; }
-
         CFCBindClass *class_binding = CFCBindClass_new(klass);
         char *class_c_data = CFCBindClass_to_c_data(class_binding);
         c_data = CFCUtil_cat(c_data, class_c_data, "\n", NULL);
@@ -342,28 +365,51 @@ S_write_parcel_c(CFCBindCore *self) {
         const char *privacy_sym = CFCClass_privacy_symbol(klass);
         privacy_syms = CFCUtil_cat(privacy_syms, "#define ",
                                    privacy_sym, "\n", NULL);
-        if (parcel && CFCClass_get_parcel(klass) != parcel) {
-            //CFCUtil_die("Multiple parcels not yet supported.");
-        }
-        parcel = CFCClass_get_parcel(klass);
     }
     vt_specs = CFCUtil_cat(vt_specs, "\n};\n", NULL);
     FREEMEM(ordered);
 
-    if (!parcel) {
-        CFCUtil_die("No source classes found.");
+    // Bootstrapping code for dependent parcels.
+    //
+    // bootstrap_inheritance() first calls bootstrap_inheritance() for all
+    // parcels from which classes are inherited. Then the VTables of the parcel
+    // are initialized. It aborts on recursive invocation.
+    //
+    // bootstrap_parcel() first calls bootstrap_inheritance() of its own
+    // parcel. Then it calls bootstrap_parcel() for all dependent parcels.
+    // Finally, it calls init_parcel(). Recursive invocation is allowed.
+
+    char *inh_bootstrap = CFCUtil_strdup("");
+    char *dep_bootstrap = CFCUtil_strdup("");
+    CFCParcel **inh_parcels = CFCParcel_inherited_parcels(parcel);
+    for (size_t i = 0; inh_parcels[i]; ++i) {
+        const char *inh_prefix = CFCParcel_get_prefix(inh_parcels[i]);
+        inh_bootstrap = CFCUtil_cat(inh_bootstrap, "    ", inh_prefix,
+                                    "bootstrap_inheritance();\n", NULL);
     }
-    //const char *prefix = CFCParcel_get_prefix(parcel);
-    const char *prefix = "lucy_";
+    FREEMEM(inh_parcels);
+    CFCParcel **dep_parcels = CFCParcel_dependent_parcels(parcel);
+    for (size_t i = 0; dep_parcels[i]; ++i) {
+        const char *dep_prefix = CFCParcel_get_prefix(dep_parcels[i]);
+        dep_bootstrap = CFCUtil_cat(dep_bootstrap, "    ", dep_prefix,
+                                    "bootstrap_parcel();\n", NULL);
+    }
+    FREEMEM(dep_parcels);
 
     char pattern[] =
         "%s\n"
         "\n"
-        "#define C_CFISH_VTABLE\n"
+        "#define C_CFISH_VTABLE\n"          // Needed for method_ptrs offset.
+        "#include <stdio.h>\n"
+        "#include <stdlib.h>\n"
         "%s\n"
         "#include \"%sparcel.h\"\n"
         "#include \"callbacks.h\"\n"
-        "#include \"Clownfish/VTable.h\"\n"
+        "#include \"Clownfish/CharBuf.h\"\n" // Needed for dump/load.
+        "#include \"Clownfish/Err.h\"\n"     // Needed for dump/load.
+        "#include \"Clownfish/Num.h\"\n"     // Needed for dump/load.
+        "#include \"Clownfish/VArray.h\"\n"  // Needed for dump/load.
+        "#include \"Clownfish/VTable.h\"\n"  // Needed for method_ptrs offset.
         "%s\n"
         "\n"
         "%s\n"
@@ -372,20 +418,37 @@ S_write_parcel_c(CFCBindCore *self) {
         " */\n"
         "%s\n"
         "\n"
+        "static int bootstrap_state = 0;\n"
+        "\n"
         "void\n"
-        "%sbootstrap_parcel() {\n"
-        "    static bool bootstrapped = false;\n"
-        "    if (bootstrapped) { return; }\n"
+        "%sbootstrap_inheritance() {\n"
+        "    if (bootstrap_state == 1) {\n"
+        "        fprintf(stderr, \"Cycle in class inheritance between\"\n"
+        "                        \" parcels detected.\\n\");\n"
+        "        abort();\n"
+        "    }\n"
+        "    if (bootstrap_state >= 2) { return; }\n"
+        "    bootstrap_state = 1;\n"
+        "%s" // Bootstrap inherited parcels.
         "    cfish_VTable_bootstrap(vtable_specs, %d);\n"
+        "    bootstrap_state = 2;\n"
+        "}\n"
+        "\n"
+        "void\n"
+        "%sbootstrap_parcel() {\n"
+        "    if (bootstrap_state >= 3) { return; }\n"
+        "    %sbootstrap_inheritance();\n"
+        "    bootstrap_state = 3;\n"
+        "%s" // Finish bootstrapping of all dependent parcels.
         "    %sinit_parcel();\n"
-        "    bootstrapped = true;\n"
         "}\n"
         "\n"
         "%s\n";
     char *file_content
         = CFCUtil_sprintf(pattern, self->header, privacy_syms, prefix,
-                          includes, c_data, vt_specs, prefix, num_specs,
-                          prefix, self->footer);
+                          includes, c_data, vt_specs, prefix, inh_bootstrap,
+                          num_specs, prefix, prefix, dep_bootstrap, prefix,
+                          self->footer);
 
     // Unlink then open file.
     const char *src_dest = CFCHierarchy_get_source_dest(hierarchy);
@@ -399,6 +462,8 @@ S_write_parcel_c(CFCBindCore *self) {
     FREEMEM(includes);
     FREEMEM(c_data);
     FREEMEM(vt_specs);
+    FREEMEM(inh_bootstrap);
+    FREEMEM(dep_bootstrap);
     FREEMEM(file_content);
 }
 
@@ -409,7 +474,6 @@ void
 CFCBindCore_write_callbacks_h(CFCBindCore *self) {
     CFCHierarchy  *hierarchy   = self->hierarchy;
     CFCClass     **ordered     = CFCHierarchy_ordered_classes(hierarchy);
-    CFCParcel     *parcel      = NULL;
     char          *includes    = CFCUtil_strdup("");
     char          *all_cb_decs = CFCUtil_strdup("");
 
@@ -426,22 +490,11 @@ CFCBindCore_write_callbacks_h(CFCBindCore *self) {
             all_cb_decs = CFCUtil_cat(all_cb_decs, cb_decs, NULL);
             FREEMEM(cb_decs);
             CFCBase_decref((CFCBase*)class_binding);
-
-            if (parcel && CFCClass_get_parcel(klass) != parcel) {
-                //CFCUtil_die("Multiple parcels not yet supported.");
-            }
-            parcel = CFCClass_get_parcel(klass);
         }
     }
 
     FREEMEM(ordered);
 
-    if (!parcel) {
-        CFCUtil_die("No source classes found.");
-    }
-    //const char *prefix = CFCParcel_get_prefix(parcel);
-    const char *prefix = "lucy_";
-
     const char pattern[] =
         "%s\n"
         "#ifndef CFCCALLBACKS_H\n"
@@ -451,7 +504,6 @@ CFCBindCore_write_callbacks_h(CFCBindCore *self) {
         "extern \"C\" {\n"
         "#endif\n"
         "\n"
-        "#include \"%sparcel.h\"\n"
         "%s"
         "\n"
         "%s"
@@ -465,7 +517,7 @@ CFCBindCore_write_callbacks_h(CFCBindCore *self) {
         "%s\n"
         "\n";
     char *file_content
-        = CFCUtil_sprintf(pattern, self->header, prefix, includes, all_cb_decs,
+        = CFCUtil_sprintf(pattern, self->header, includes, all_cb_decs,
                           self->footer);
 
     // Unlink then write file.

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/src/CFCParcel.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParcel.c b/clownfish/compiler/src/CFCParcel.c
index de2c3bc..fe4f27a 100644
--- a/clownfish/compiler/src/CFCParcel.c
+++ b/clownfish/compiler/src/CFCParcel.c
@@ -37,6 +37,7 @@ struct CFCParcel {
     char *prefix;
     char *Prefix;
     char *PREFIX;
+    char *privacy_sym;
     int is_included;
     char **dependent_parcels;
     size_t num_dependent_parcels;
@@ -217,6 +218,15 @@ CFCParcel_init(CFCParcel *self, const char *name, const char *cnick,
     self->Prefix[prefix_len] = '\0';
     self->PREFIX[prefix_len] = '\0';
 
+    // Derive privacy symbol.
+    size_t privacy_sym_len = cnick_len + 4;
+    self->privacy_sym = (char*)MALLOCATE(privacy_sym_len + 1);
+    memcpy(self->privacy_sym, "CFP_", 4);
+    for (size_t i = 0; i < cnick_len; i++) {
+        self->privacy_sym[i+4] = toupper(self->cnick[i]);
+    }
+    self->privacy_sym[privacy_sym_len] = '\0';
+
     // Set is_included.
     self->is_included = is_included;
 
@@ -314,6 +324,7 @@ CFCParcel_destroy(CFCParcel *self) {
     FREEMEM(self->prefix);
     FREEMEM(self->Prefix);
     FREEMEM(self->PREFIX);
+    FREEMEM(self->privacy_sym);
     for (size_t i = 0; self->dependent_parcels[i]; ++i) {
         FREEMEM(self->dependent_parcels[i]);
     }
@@ -374,6 +385,11 @@ CFCParcel_get_PREFIX(CFCParcel *self) {
     return self->PREFIX;
 }
 
+const char*
+CFCParcel_get_privacy_sym(CFCParcel *self) {
+    return self->privacy_sym;
+}
+
 int
 CFCParcel_included(CFCParcel *self) {
     return self->is_included;

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/src/CFCParcel.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParcel.h b/clownfish/compiler/src/CFCParcel.h
index c269fe0..d937297 100644
--- a/clownfish/compiler/src/CFCParcel.h
+++ b/clownfish/compiler/src/CFCParcel.h
@@ -110,6 +110,11 @@ CFCParcel_get_Prefix(CFCParcel *self);
 const char*
 CFCParcel_get_PREFIX(CFCParcel *self);
 
+/* Return the Parcel's privacy symbol.
+ */
+const char*
+CFCParcel_get_privacy_sym(CFCParcel *self);
+
 /** Return true if the parcel is from an include directory.
  */
 int

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/src/CFCPerl.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCPerl.c b/clownfish/compiler/src/CFCPerl.c
index 7263632..37f8b19 100644
--- a/clownfish/compiler/src/CFCPerl.c
+++ b/clownfish/compiler/src/CFCPerl.c
@@ -36,19 +36,13 @@
 
 struct CFCPerl {
     CFCBase base;
-    CFCParcel *parcel;
     CFCHierarchy *hierarchy;
     char *lib_dir;
     char *boot_class;
     char *header;
     char *footer;
     char *xs_path;
-    char *boot_h_file;
-    char *boot_c_file;
-    char *boot_h_path;
-    char *boot_c_path;
     char *boot_func;
-    char *parcel_h_file;
 };
 
 // Modify a string in place, swapping out "::" for the supplied character.
@@ -65,24 +59,20 @@ static const CFCMeta CFCPERL_META = {
 };
 
 CFCPerl*
-CFCPerl_new(CFCParcel *parcel, CFCHierarchy *hierarchy, const char *lib_dir,
+CFCPerl_new(CFCHierarchy *hierarchy, const char *lib_dir,
             const char *boot_class, const char *header, const char *footer) {
     CFCPerl *self = (CFCPerl*)CFCBase_allocate(&CFCPERL_META);
-    return CFCPerl_init(self, parcel, hierarchy, lib_dir, boot_class, header,
-                        footer);
+    return CFCPerl_init(self, hierarchy, lib_dir, boot_class, header, footer);
 }
 
 CFCPerl*
-CFCPerl_init(CFCPerl *self, CFCParcel *parcel, CFCHierarchy *hierarchy,
-             const char *lib_dir, const char *boot_class, const char *header,
-             const char *footer) {
-    CFCUTIL_NULL_CHECK(parcel);
+CFCPerl_init(CFCPerl *self, CFCHierarchy *hierarchy, const char *lib_dir,
+             const char *boot_class, const char *header, const char *footer) {
     CFCUTIL_NULL_CHECK(hierarchy);
     CFCUTIL_NULL_CHECK(lib_dir);
     CFCUTIL_NULL_CHECK(boot_class);
     CFCUTIL_NULL_CHECK(header);
     CFCUTIL_NULL_CHECK(footer);
-    self->parcel     = (CFCParcel*)CFCBase_incref((CFCBase*)parcel);
     self->hierarchy  = (CFCHierarchy*)CFCBase_incref((CFCBase*)hierarchy);
     self->lib_dir    = CFCUtil_strdup(lib_dir);
     self->boot_class = CFCUtil_strdup(boot_class);
@@ -94,47 +84,26 @@ CFCPerl_init(CFCPerl *self, CFCParcel *parcel, CFCHierarchy *hierarchy,
                                     boot_class);
     S_replace_double_colons(self->xs_path, CHY_DIR_SEP_CHAR);
 
-    // Derive the name of the files containing bootstrapping code.
-    const char *prefix   = CFCParcel_get_prefix(parcel);
-    const char *inc_dest = CFCHierarchy_get_include_dest(hierarchy);
-    const char *src_dest = CFCHierarchy_get_source_dest(hierarchy);
-    self->boot_h_file = CFCUtil_sprintf("%sboot.h", prefix);
-    self->boot_c_file = CFCUtil_sprintf("%sboot.c", prefix);
-    self->boot_h_path = CFCUtil_sprintf("%s" CHY_DIR_SEP "%s", inc_dest,
-                                        self->boot_h_file);
-    self->boot_c_path = CFCUtil_sprintf("%s" CHY_DIR_SEP "%s", src_dest,
-                                        self->boot_c_file);
-
     // Derive the name of the bootstrap function.
-    self->boot_func = CFCUtil_sprintf("%s%s_bootstrap", prefix, boot_class);
+    self->boot_func = CFCUtil_sprintf("cfish_%s_bootstrap", boot_class);
     for (int i = 0; self->boot_func[i] != 0; i++) {
         if (!isalnum(self->boot_func[i])) {
             self->boot_func[i] = '_';
         }
     }
 
-    // Derive the name of the "parcel.h" file.
-    //self->parcel_h_file = CFCUtil_sprintf("%sparcel.h", prefix);
-    self->parcel_h_file = CFCUtil_sprintf("%sparcel.h", "lucy_");
-
     return self;
 }
 
 void
 CFCPerl_destroy(CFCPerl *self) {
-    CFCBase_decref((CFCBase*)self->parcel);
     CFCBase_decref((CFCBase*)self->hierarchy);
     FREEMEM(self->lib_dir);
     FREEMEM(self->boot_class);
     FREEMEM(self->header);
     FREEMEM(self->footer);
     FREEMEM(self->xs_path);
-    FREEMEM(self->boot_h_file);
-    FREEMEM(self->boot_c_file);
-    FREEMEM(self->boot_h_path);
-    FREEMEM(self->boot_c_path);
     FREEMEM(self->boot_func);
-    FREEMEM(self->parcel_h_file);
     CFCBase_destroy((CFCBase*)self);
 }
 
@@ -221,7 +190,11 @@ S_write_boot_h(CFCPerl *self) {
     char *content
         = CFCUtil_sprintf(pattern, self->header, guard, guard, self->boot_func,
                           guard, self->footer);
-    CFCUtil_write_file(self->boot_h_path, content, strlen(content));
+
+    const char *inc_dest = CFCHierarchy_get_include_dest(self->hierarchy);
+    char *boot_h_path = CFCUtil_sprintf("%s" CHY_DIR_SEP "boot.h", inc_dest);
+    CFCUtil_write_file(boot_h_path, content, strlen(content));
+    FREEMEM(boot_h_path);
 
     FREEMEM(content);
     FREEMEM(guard);
@@ -229,11 +202,18 @@ S_write_boot_h(CFCPerl *self) {
 
 static void
 S_write_boot_c(CFCPerl *self) {
-    CFCClass **ordered   = CFCHierarchy_ordered_classes(self->hierarchy);
-    char *pound_includes = CFCUtil_strdup("");
-    char *alias_adds     = CFCUtil_strdup("");
-    char *isa_pushes     = CFCUtil_strdup("");
-    const char *prefix   = CFCParcel_get_prefix(self->parcel);
+    CFCClass  **ordered   = CFCHierarchy_ordered_classes(self->hierarchy);
+    CFCParcel **parcels   = CFCParcel_source_parcels();
+    char *pound_includes  = CFCUtil_strdup("");
+    char *bootstrap_code  = CFCUtil_strdup("");
+    char *alias_adds      = CFCUtil_strdup("");
+    char *isa_pushes      = CFCUtil_strdup("");
+
+    for (size_t i = 0; parcels[i]; ++i) {
+        const char *prefix = CFCParcel_get_prefix(parcels[i]);
+        bootstrap_code = CFCUtil_cat(bootstrap_code, "    ", prefix,
+                                     "bootstrap_parcel();\n", NULL);
+    }
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
@@ -284,18 +264,18 @@ S_write_boot_c(CFCPerl *self) {
     const char pattern[] =
         "%s\n"
         "\n"
-        "#include \"%s\"\n"
+        "#include \"cfish_parcel.h\"\n"
         "#include \"EXTERN.h\"\n"
         "#include \"perl.h\"\n"
         "#include \"XSUB.h\"\n"
-        "#include \"%s\"\n"
+        "#include \"boot.h\"\n"
         "#include \"Clownfish/CharBuf.h\"\n"
         "#include \"Clownfish/VTable.h\"\n"
         "%s\n"
         "\n"
         "void\n"
         "%s() {\n"
-        "    %sbootstrap_parcel();\n"
+        "%s"
         "\n"
         "    cfish_ZombieCharBuf *alias = CFISH_ZCB_WRAP_STR(\"\", 0);\n"
         "%s"
@@ -307,15 +287,21 @@ S_write_boot_c(CFCPerl *self) {
         "%s\n"
         "\n";
     char *content
-        = CFCUtil_sprintf(pattern, self->header, self->parcel_h_file,
-                          self->boot_h_file, pound_includes, self->boot_func,
-                          prefix, alias_adds, isa_pushes, self->footer);
-    CFCUtil_write_file(self->boot_c_path, content, strlen(content));
+        = CFCUtil_sprintf(pattern, self->header, pound_includes,
+                          self->boot_func, bootstrap_code, alias_adds,
+                          isa_pushes, self->footer);
+
+    const char *src_dest = CFCHierarchy_get_source_dest(self->hierarchy);
+    char *boot_c_path = CFCUtil_sprintf("%s" CHY_DIR_SEP "boot.c", src_dest);
+    CFCUtil_write_file(boot_c_path, content, strlen(content));
+    FREEMEM(boot_c_path);
 
     FREEMEM(content);
     FREEMEM(isa_pushes);
     FREEMEM(alias_adds);
+    FREEMEM(bootstrap_code);
     FREEMEM(pound_includes);
+    FREEMEM(parcels);
     FREEMEM(ordered);
 }
 
@@ -366,8 +352,7 @@ S_xs_file_contents(CFCPerl *self, const char *generated_xs,
         "%s"
         "\n"
         "#include \"XSBind.h\"\n"
-        "#include \"%s\"\n"
-        "#include \"%s\"\n"
+        "#include \"boot.h\"\n"
         "\n"
         "#include \"Clownfish/Util/Memory.h\"\n"
         "#include \"Clownfish/Util/StringHelper.h\"\n"
@@ -389,10 +374,9 @@ S_xs_file_contents(CFCPerl *self, const char *generated_xs,
         "\n"
         "%s";
     char *contents
-        = CFCUtil_sprintf(pattern, self->header, self->parcel_h_file,
-                          self->boot_h_file, generated_xs, self->boot_class,
-                          self->boot_class, xs_init, hand_rolled_xs,
-                          self->footer);
+        = CFCUtil_sprintf(pattern, self->header, generated_xs,
+                          self->boot_class, self->boot_class, xs_init,
+                          hand_rolled_xs, self->footer);
 
     return contents;
 }
@@ -504,7 +488,6 @@ S_write_callbacks_c(CFCPerl *self) {
         "\n"
         "#include \"XSBind.h\"\n"
         "#include \"callbacks.h\"\n"
-        "#include \"%s\"\n"
         "\n"
         "static void\n"
         "S_finish_callback_void(const char *meth_name) {\n"
@@ -577,8 +560,7 @@ S_write_callbacks_c(CFCPerl *self) {
         "    return retval;\n"
         "}\n"
         "\n";
-    char *content
-        = CFCUtil_sprintf(pattern, self->header, self->parcel_h_file);
+    char *content = CFCUtil_sprintf(pattern, self->header);
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/clownfish/compiler/src/CFCPerl.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCPerl.h b/clownfish/compiler/src/CFCPerl.h
index 04f0c53..eef10ac 100644
--- a/clownfish/compiler/src/CFCPerl.h
+++ b/clownfish/compiler/src/CFCPerl.h
@@ -67,14 +67,13 @@ struct CFCHierarchy;
  * typically copyright information.
  */
 CFCPerl*
-CFCPerl_new(struct CFCParcel *parcel, struct CFCHierarchy *hierarchy,
-            const char *lib_dir, const char *boot_class, const char *header,
-            const char *footer);
+CFCPerl_new(struct CFCHierarchy *hierarchy, const char *lib_dir,
+            const char *boot_class, const char *header, const char *footer);
 
 CFCPerl*
-CFCPerl_init(CFCPerl *self, struct CFCParcel *parcel,
-             struct CFCHierarchy *hierarchy, const char *lib_dir,
-             const char *boot_class, const char *header, const char *footer);
+CFCPerl_init(CFCPerl *self, struct CFCHierarchy *hierarchy,
+             const char *lib_dir, const char *boot_class, const char *header,
+             const char *footer);
 
 void
 CFCPerl_destroy(CFCPerl *self);

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/common/charmonizer.c b/common/charmonizer.c
index eda0a12..267e1a5 100644
--- a/common/charmonizer.c
+++ b/common/charmonizer.c
@@ -6832,6 +6832,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
         chaz_CFlags_add_define(extra_cflags, "HAS_BOOL", NULL);
     }
 
+    chaz_CFlags_add_define(extra_cflags, "CFP_CFISH", NULL);
     chaz_CFlags_add_define(extra_cflags, "CFP_LUCY", NULL);
 }
 
@@ -6984,6 +6985,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     free(scratch);
 
     scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
+                             "cfish_parcel", obj_ext, NULL);
+    chaz_MakeVar_append(var, scratch);
+    free(scratch);
+    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
                              "lucy_parcel", obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
@@ -7023,6 +7028,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     free(scratch);
 
     /* Needed for parallel builds. */
+    scratch = chaz_Util_join(dir_sep, "autogen", "source", "cfish_parcel.c",
+                             NULL);
+    rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
+    free(scratch);
     scratch = chaz_Util_join(dir_sep, "autogen", "source", "lucy_parcel.c",
                              NULL);
     rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 99a28c3..d7236fb 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -90,6 +90,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
         chaz_CFlags_add_define(extra_cflags, "HAS_BOOL", NULL);
     }
 
+    chaz_CFlags_add_define(extra_cflags, "CFP_CFISH", NULL);
     chaz_CFlags_add_define(extra_cflags, "CFP_LUCY", NULL);
 }
 
@@ -242,6 +243,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     free(scratch);
 
     scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
+                             "cfish_parcel", obj_ext, NULL);
+    chaz_MakeVar_append(var, scratch);
+    free(scratch);
+    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
                              "lucy_parcel", obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
@@ -281,6 +286,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     free(scratch);
 
     /* Needed for parallel builds. */
+    scratch = chaz_Util_join(dir_sep, "autogen", "source", "cfish_parcel.c",
+                             NULL);
+    rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
+    free(scratch);
     scratch = chaz_Util_join(dir_sep, "autogen", "source", "lucy_parcel.c",
                              NULL);
     rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/core/Clownfish.c
----------------------------------------------------------------------
diff --git a/core/Clownfish.c b/core/Clownfish.c
new file mode 100644
index 0000000..130b87a
--- /dev/null
+++ b/core/Clownfish.c
@@ -0,0 +1,27 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Clownfish/Num.h"
+#include "Clownfish/Hash.h"
+#include "Clownfish/Err.h"
+
+void
+cfish_init_parcel() {
+    cfish_Bool_init_class();
+    cfish_Hash_init_class();
+    cfish_Err_init_class();
+}
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/core/Lucy.c
----------------------------------------------------------------------
diff --git a/core/Lucy.c b/core/Lucy.c
index ebd0c0b..4bbfad5 100644
--- a/core/Lucy.c
+++ b/core/Lucy.c
@@ -14,14 +14,7 @@
  * limitations under the License.
  */
 
-#include "Clownfish/Num.h"
-#include "Clownfish/Hash.h"
-#include "Clownfish/Err.h"
-
 void
 lucy_init_parcel() {
-    cfish_Bool_init_class();
-    cfish_Hash_init_class();
-    cfish_Err_init_class();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/perl/Build.PL
----------------------------------------------------------------------
diff --git a/perl/Build.PL b/perl/Build.PL
index db8a3d9..ce003dc 100644
--- a/perl/Build.PL
+++ b/perl/Build.PL
@@ -68,7 +68,7 @@ my $builder = Lucy::Build->new(
             $UTF8PROC_SRC_DIR,
         ],
     },
-    extra_compiler_flags => '-DCFP_LUCY',
+    extra_compiler_flags => '-DCFP_CFISH -DCFP_LUCY',
     add_to_cleanup => [
         qw(
             Lucy-*

http://git-wip-us.apache.org/repos/asf/lucy/blob/32fe546c/perl/buildlib/Lucy/Build/Binding/Misc.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Misc.pm b/perl/buildlib/Lucy/Build/Binding/Misc.pm
index 0e25807..c1377e0 100644
--- a/perl/buildlib/Lucy/Build/Binding/Misc.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Misc.pm
@@ -32,7 +32,7 @@ sub bind_lucy {
 MODULE = Lucy    PACKAGE = Lucy
 
 BOOT:
-    lucy_Lucy_bootstrap();
+    cfish_Lucy_bootstrap();
 
 IV
 _dummy_function()


[lucy-commits] [21/26] Rework Clownfish test harness

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolder.c b/core/Lucy/Test/Store/TestFolder.c
index ce7d417..2c2662e 100644
--- a/core/Lucy/Test/Store/TestFolder.c
+++ b/core/Lucy/Test/Store/TestFolder.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFolder.h"
 #include "Lucy/Store/DirHandle.h"
@@ -40,14 +40,8 @@ static CharBuf *foo_foo           = NULL;
 static CharBuf *nope              = NULL;
 
 TestFolder*
-TestFolder_new(TestFormatter *formatter) {
-    TestFolder *self = (TestFolder*)VTable_Make_Obj(TESTFOLDER);
-    return TestFolder_init(self, formatter);
-}
-
-TestFolder*
-TestFolder_init(TestFolder *self, TestFormatter *formatter) {
-    return (TestFolder*)TestBatch_init((TestBatch*)self, 79, formatter);
+TestFolder_new() {
+    return (TestFolder*)VTable_Make_Obj(TESTFOLDER);
 }
 
 static void
@@ -81,7 +75,7 @@ S_destroy_strings(void) {
 }
 
 static void
-test_Exists(TestBatch *batch) {
+test_Exists(TestBatchRunner *runner) {
     Folder *folder = (Folder*)RAMFolder_new(NULL);
     FileHandle *fh;
 
@@ -93,80 +87,80 @@ test_Exists(TestBatch *batch) {
                                 FH_CREATE | FH_WRITE_ONLY);
     DECREF(fh);
 
-    TEST_TRUE(batch, Folder_Exists(folder, foo), "Dir exists");
-    TEST_TRUE(batch, Folder_Exists(folder, boffo), "File exists");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_bar),
+    TEST_TRUE(runner, Folder_Exists(folder, foo), "Dir exists");
+    TEST_TRUE(runner, Folder_Exists(folder, boffo), "File exists");
+    TEST_TRUE(runner, Folder_Exists(folder, foo_bar),
               "Nested dir exists");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "Nested file exists");
 
-    TEST_FALSE(batch, Folder_Exists(folder, banana),
+    TEST_FALSE(runner, Folder_Exists(folder, banana),
                "Non-existent entry");
-    TEST_FALSE(batch, Folder_Exists(folder, foo_foo),
+    TEST_FALSE(runner, Folder_Exists(folder, foo_foo),
                "Non-existent nested entry");
 
     DECREF(folder);
 }
 
 static void
-test_Set_Path_and_Get_Path(TestBatch *batch) {
+test_Set_Path_and_Get_Path(TestBatchRunner *runner) {
     Folder *folder = (Folder*)RAMFolder_new(foo);
-    TEST_TRUE(batch, CB_Equals(Folder_Get_Path(folder), (Obj*)foo),
+    TEST_TRUE(runner, CB_Equals(Folder_Get_Path(folder), (Obj*)foo),
               "Get_Path");
     Folder_Set_Path(folder, bar);
-    TEST_TRUE(batch, CB_Equals(Folder_Get_Path(folder), (Obj*)bar),
+    TEST_TRUE(runner, CB_Equals(Folder_Get_Path(folder), (Obj*)bar),
               "Set_Path");
     DECREF(folder);
 }
 
 static void
-test_MkDir_and_Is_Directory(TestBatch *batch) {
+test_MkDir_and_Is_Directory(TestBatchRunner *runner) {
     Folder *folder = (Folder*)RAMFolder_new(NULL);
     FileHandle *fh;
 
-    TEST_FALSE(batch, Folder_Is_Directory(folder, foo),
+    TEST_FALSE(runner, Folder_Is_Directory(folder, foo),
                "Is_Directory() false for non-existent entry");
 
-    TEST_TRUE(batch, Folder_MkDir(folder, foo),
+    TEST_TRUE(runner, Folder_MkDir(folder, foo),
               "MkDir returns true on success");
-    TEST_TRUE(batch, Folder_Is_Directory(folder, foo),
+    TEST_TRUE(runner, Folder_Is_Directory(folder, foo),
               "Is_Directory() true for local folder");
 
-    TEST_FALSE(batch, Folder_Is_Directory(folder, foo_bar_baz),
+    TEST_FALSE(runner, Folder_Is_Directory(folder, foo_bar_baz),
                "Is_Directory() false for non-existent deeply nested dir");
     Err_set_error(NULL);
-    TEST_FALSE(batch, Folder_MkDir(folder, foo_bar_baz),
+    TEST_FALSE(runner, Folder_MkDir(folder, foo_bar_baz),
                "MkDir for deeply nested dir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "MkDir for deeply nested dir sets Err_error");
 
-    TEST_TRUE(batch, Folder_MkDir(folder, foo_bar),
+    TEST_TRUE(runner, Folder_MkDir(folder, foo_bar),
               "MkDir for nested dir");
-    TEST_TRUE(batch, Folder_Is_Directory(folder, foo_bar),
+    TEST_TRUE(runner, Folder_Is_Directory(folder, foo_bar),
               "Is_Directory() true for nested dir");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, Folder_MkDir(folder, foo_bar),
+    TEST_FALSE(runner, Folder_MkDir(folder, foo_bar),
                "Overwrite dir with MkDir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Overwrite dir with MkDir sets Err_error");
 
     fh = Folder_Open_FileHandle(folder, foo_boffo,
                                 FH_CREATE | FH_WRITE_ONLY);
     DECREF(fh);
     Err_set_error(NULL);
-    TEST_FALSE(batch, Folder_MkDir(folder, foo_boffo),
+    TEST_FALSE(runner, Folder_MkDir(folder, foo_boffo),
                "Overwrite file with MkDir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Overwrite file with MkDir sets Err_error");
-    TEST_FALSE(batch, Folder_Is_Directory(folder, foo_boffo),
+    TEST_FALSE(runner, Folder_Is_Directory(folder, foo_boffo),
                "Is_Directory() false for nested file");
 
     DECREF(folder);
 }
 
 static void
-test_Enclosing_Folder_and_Find_Folder(TestBatch *batch) {
+test_Enclosing_Folder_and_Find_Folder(TestBatchRunner *runner) {
     Folder *folder = (Folder*)RAMFolder_new(NULL);
     FileHandle *fh;
 
@@ -179,21 +173,21 @@ test_Enclosing_Folder_and_Find_Folder(TestBatch *batch) {
     {
         Folder *encloser = Folder_Enclosing_Folder(folder, (CharBuf*)nope);
         Folder *found = Folder_Find_Folder(folder, (CharBuf*)nope);
-        TEST_TRUE(batch, encloser == folder,
+        TEST_TRUE(runner, encloser == folder,
                   "Enclosing_Folder() - non-existent entry yields parent");
-        TEST_TRUE(batch, found == NULL,
+        TEST_TRUE(runner, found == NULL,
                   "Find_Folder() - non-existent entry yields NULL");
     }
 
     {
         Folder *encloser = Folder_Enclosing_Folder(folder, foo_bar);
         Folder *found = Folder_Find_Folder(folder, foo_bar);
-        TEST_TRUE(batch,
+        TEST_TRUE(runner,
                   encloser
                   && Folder_Is_A(encloser, FOLDER)
                   && CB_Ends_With(Folder_Get_Path(encloser), foo),
                   "Enclosing_Folder() - find one directory down");
-        TEST_TRUE(batch,
+        TEST_TRUE(runner,
                   found
                   && Folder_Is_A(found, FOLDER)
                   && CB_Ends_With(Folder_Get_Path(found), bar),
@@ -203,12 +197,12 @@ test_Enclosing_Folder_and_Find_Folder(TestBatch *batch) {
     {
         Folder *encloser = Folder_Enclosing_Folder(folder, foo_bar_baz);
         Folder *found = Folder_Find_Folder(folder, foo_bar_baz);
-        TEST_TRUE(batch,
+        TEST_TRUE(runner,
                   encloser
                   && Folder_Is_A(encloser, FOLDER)
                   && CB_Ends_With(Folder_Get_Path(encloser), bar),
                   "Find two directories down");
-        TEST_TRUE(batch,
+        TEST_TRUE(runner,
                   found
                   && Folder_Is_A(found, FOLDER)
                   && CB_Ends_With(Folder_Get_Path(found), baz),
@@ -219,12 +213,12 @@ test_Enclosing_Folder_and_Find_Folder(TestBatch *batch) {
         Folder *encloser
             = Folder_Enclosing_Folder(folder, foo_bar_baz_boffo);
         Folder *found = Folder_Find_Folder(folder, foo_bar_baz_boffo);
-        TEST_TRUE(batch,
+        TEST_TRUE(runner,
                   encloser
                   && Folder_Is_A(encloser, FOLDER)
                   && CB_Ends_With(Folder_Get_Path(encloser), baz),
                   "Recurse to find a directory containing a real file");
-        TEST_TRUE(batch, found == NULL,
+        TEST_TRUE(runner, found == NULL,
                   "Find_Folder() - file instead of folder yields NULL");
     }
 
@@ -233,7 +227,7 @@ test_Enclosing_Folder_and_Find_Folder(TestBatch *batch) {
 }
 
 static void
-test_List(TestBatch *batch) {
+test_List(TestBatchRunner *runner) {
     Folder     *folder = (Folder*)RAMFolder_new(NULL);
     FileHandle *fh;
     VArray     *list;
@@ -249,21 +243,21 @@ test_List(TestBatch *batch) {
 
     list = Folder_List(folder, NULL);
     VA_Sort(list, NULL, NULL);
-    TEST_INT_EQ(batch, VA_Get_Size(list), 3, "List");
+    TEST_INT_EQ(runner, VA_Get_Size(list), 3, "List");
     elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 0), CHARBUF);
-    TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)banana),
+    TEST_TRUE(runner, elem && CB_Equals(elem, (Obj*)banana),
               "List first file");
     elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 1), CHARBUF);
-    TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)boffo),
+    TEST_TRUE(runner, elem && CB_Equals(elem, (Obj*)boffo),
               "List second file");
     elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 2), CHARBUF);
-    TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)foo), "List dir");
+    TEST_TRUE(runner, elem && CB_Equals(elem, (Obj*)foo), "List dir");
     DECREF(list);
 
     list = Folder_List(folder, foo_bar);
-    TEST_INT_EQ(batch, VA_Get_Size(list), 1, "List subdirectory contents");
+    TEST_INT_EQ(runner, VA_Get_Size(list), 1, "List subdirectory contents");
     elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 0), CHARBUF);
-    TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)baz),
+    TEST_TRUE(runner, elem && CB_Equals(elem, (Obj*)baz),
               "Just the filename");
     DECREF(list);
 
@@ -271,7 +265,7 @@ test_List(TestBatch *batch) {
 }
 
 static void
-test_Open_Dir(TestBatch *batch) {
+test_Open_Dir(TestBatchRunner *runner) {
     Folder     *folder = (Folder*)RAMFolder_new(NULL);
     DirHandle  *dh;
 
@@ -279,107 +273,107 @@ test_Open_Dir(TestBatch *batch) {
     Folder_MkDir(folder, foo_bar);
 
     dh = Folder_Open_Dir(folder, foo);
-    TEST_TRUE(batch, dh && DH_Is_A(dh, DIRHANDLE), "Open_Dir");
+    TEST_TRUE(runner, dh && DH_Is_A(dh, DIRHANDLE), "Open_Dir");
     DECREF(dh);
     dh = Folder_Open_Dir(folder, foo_bar);
-    TEST_TRUE(batch, dh && DH_Is_A(dh, DIRHANDLE), "Open_Dir nested dir");
+    TEST_TRUE(runner, dh && DH_Is_A(dh, DIRHANDLE), "Open_Dir nested dir");
     DECREF(dh);
 
     Err_set_error(NULL);
     dh = Folder_Open_Dir(folder, bar);
-    TEST_TRUE(batch, dh == NULL,
+    TEST_TRUE(runner, dh == NULL,
               "Open_Dir on non-existent entry fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Open_Dir on non-existent entry sets Err_error");
 
     Err_set_error(NULL);
     dh = Folder_Open_Dir(folder, foo_foo);
-    TEST_TRUE(batch, dh == NULL,
+    TEST_TRUE(runner, dh == NULL,
               "Open_Dir on non-existent nested entry fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Open_Dir on non-existent nested entry sets Err_error");
 
     DECREF(folder);
 }
 
 static void
-test_Open_FileHandle(TestBatch *batch) {
+test_Open_FileHandle(TestBatchRunner *runner) {
     Folder     *folder = (Folder*)RAMFolder_new(NULL);
     FileHandle *fh;
 
     Folder_MkDir(folder, foo);
 
     fh = Folder_Open_FileHandle(folder, boffo, FH_CREATE | FH_WRITE_ONLY);
-    TEST_TRUE(batch, fh && FH_Is_A(fh, FILEHANDLE), "Open_FileHandle");
+    TEST_TRUE(runner, fh && FH_Is_A(fh, FILEHANDLE), "Open_FileHandle");
     DECREF(fh);
 
     fh = Folder_Open_FileHandle(folder, foo_boffo,
                                 FH_CREATE | FH_WRITE_ONLY);
-    TEST_TRUE(batch, fh && FH_Is_A(fh, FILEHANDLE),
+    TEST_TRUE(runner, fh && FH_Is_A(fh, FILEHANDLE),
               "Open_FileHandle for nested file");
     DECREF(fh);
 
     Err_set_error(NULL);
     fh = Folder_Open_FileHandle(folder, foo, FH_CREATE | FH_WRITE_ONLY);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "Open_FileHandle on existing dir path fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Open_FileHandle on existing dir name sets Err_error");
 
     Err_set_error(NULL);
     fh = Folder_Open_FileHandle(folder, foo_bar_baz_boffo,
                                 FH_CREATE | FH_WRITE_ONLY);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "Open_FileHandle for entry within non-existent dir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Open_FileHandle for entry within non-existent dir sets Err_error");
 
     DECREF(folder);
 }
 
 static void
-test_Open_Out(TestBatch *batch) {
+test_Open_Out(TestBatchRunner *runner) {
     Folder    *folder = (Folder*)RAMFolder_new(NULL);
     OutStream *outstream;
 
     Folder_MkDir(folder, foo);
 
     outstream = Folder_Open_Out(folder, boffo);
-    TEST_TRUE(batch, outstream && OutStream_Is_A(outstream, OUTSTREAM),
+    TEST_TRUE(runner, outstream && OutStream_Is_A(outstream, OUTSTREAM),
               "Open_Out");
     DECREF(outstream);
 
     outstream = Folder_Open_Out(folder, foo_boffo);
-    TEST_TRUE(batch, outstream && OutStream_Is_A(outstream, OUTSTREAM),
+    TEST_TRUE(runner, outstream && OutStream_Is_A(outstream, OUTSTREAM),
               "Open_Out for nested file");
     DECREF(outstream);
 
     Err_set_error(NULL);
     outstream = Folder_Open_Out(folder, boffo);
-    TEST_TRUE(batch, outstream == NULL,
+    TEST_TRUE(runner, outstream == NULL,
               "Open_OutStream on existing file fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Open_Out on existing file sets Err_error");
 
     Err_set_error(NULL);
     outstream = Folder_Open_Out(folder, foo);
-    TEST_TRUE(batch, outstream == NULL,
+    TEST_TRUE(runner, outstream == NULL,
               "Open_OutStream on existing dir path fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Open_Out on existing dir name sets Err_error");
 
     Err_set_error(NULL);
     outstream = Folder_Open_Out(folder, foo_bar_baz_boffo);
-    TEST_TRUE(batch, outstream == NULL,
+    TEST_TRUE(runner, outstream == NULL,
               "Open_Out for entry within non-existent dir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Open_Out for entry within non-existent dir sets Err_error");
 
     DECREF(folder);
 }
 
 static void
-test_Open_In(TestBatch *batch) {
+test_Open_In(TestBatchRunner *runner) {
     Folder     *folder = (Folder*)RAMFolder_new(NULL);
     FileHandle *fh;
     InStream   *instream;
@@ -392,34 +386,34 @@ test_Open_In(TestBatch *batch) {
     DECREF(fh);
 
     instream = Folder_Open_In(folder, boffo);
-    TEST_TRUE(batch, instream && InStream_Is_A(instream, INSTREAM),
+    TEST_TRUE(runner, instream && InStream_Is_A(instream, INSTREAM),
               "Open_In");
     DECREF(instream);
 
     instream = Folder_Open_In(folder, foo_boffo);
-    TEST_TRUE(batch, instream && InStream_Is_A(instream, INSTREAM),
+    TEST_TRUE(runner, instream && InStream_Is_A(instream, INSTREAM),
               "Open_In for nested file");
     DECREF(instream);
 
     Err_set_error(NULL);
     instream = Folder_Open_In(folder, foo);
-    TEST_TRUE(batch, instream == NULL,
+    TEST_TRUE(runner, instream == NULL,
               "Open_InStream on existing dir path fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Open_In on existing dir name sets Err_error");
 
     Err_set_error(NULL);
     instream = Folder_Open_In(folder, foo_bar_baz_boffo);
-    TEST_TRUE(batch, instream == NULL,
+    TEST_TRUE(runner, instream == NULL,
               "Open_In for entry within non-existent dir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Open_In for entry within non-existent dir sets Err_error");
 
     DECREF(folder);
 }
 
 static void
-test_Delete(TestBatch *batch) {
+test_Delete(TestBatchRunner *runner) {
     Folder *folder = (Folder*)RAMFolder_new(NULL);
     FileHandle *fh;
     bool result;
@@ -434,28 +428,28 @@ test_Delete(TestBatch *batch) {
 
     Err_set_error(NULL);
     result = Folder_Delete(folder, banana);
-    TEST_FALSE(batch, result, "Delete on non-existent entry returns false");
+    TEST_FALSE(runner, result, "Delete on non-existent entry returns false");
 
     Err_set_error(NULL);
     result = Folder_Delete(folder, foo);
-    TEST_FALSE(batch, result, "Delete on non-empty dir returns false");
+    TEST_FALSE(runner, result, "Delete on non-empty dir returns false");
 
-    TEST_TRUE(batch, Folder_Delete(folder, foo_boffo),
+    TEST_TRUE(runner, Folder_Delete(folder, foo_boffo),
               "Delete nested file");
-    TEST_FALSE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_FALSE(runner, Folder_Exists(folder, foo_boffo),
                "File is really gone");
-    TEST_TRUE(batch, Folder_Delete(folder, foo_bar),
+    TEST_TRUE(runner, Folder_Delete(folder, foo_bar),
               "Delete nested dir");
-    TEST_FALSE(batch, Folder_Exists(folder, foo_bar),
+    TEST_FALSE(runner, Folder_Exists(folder, foo_bar),
                "Dir is really gone");
-    TEST_TRUE(batch, Folder_Delete(folder, foo), "Delete empty dir");
-    TEST_FALSE(batch, Folder_Exists(folder, foo), "Dir is really gone");
+    TEST_TRUE(runner, Folder_Delete(folder, foo), "Delete empty dir");
+    TEST_FALSE(runner, Folder_Exists(folder, foo), "Dir is really gone");
 
     DECREF(folder);
 }
 
 static void
-test_Delete_Tree(TestBatch *batch) {
+test_Delete_Tree(TestBatchRunner *runner) {
     Folder *folder = (Folder*)RAMFolder_new(NULL);
     FileHandle *fh;
     bool result;
@@ -474,19 +468,19 @@ test_Delete_Tree(TestBatch *batch) {
     DECREF(fh);
 
     result = Folder_Delete_Tree(folder, foo);
-    TEST_TRUE(batch, result, "Delete_Tree() succeeded");
-    TEST_FALSE(batch, Folder_Exists(folder, foo), "Tree really gone");
+    TEST_TRUE(runner, result, "Delete_Tree() succeeded");
+    TEST_FALSE(runner, Folder_Exists(folder, foo), "Tree really gone");
 
-    TEST_TRUE(batch, Folder_Exists(folder, bar),
+    TEST_TRUE(runner, Folder_Exists(folder, bar),
               "local dir with same name as nested dir left intact");
-    TEST_TRUE(batch, Folder_Exists(folder, baz),
+    TEST_TRUE(runner, Folder_Exists(folder, baz),
               "local file with same name as nested dir left intact");
 
     // Kill off the bystanders.
     result = Folder_Delete_Tree(folder, bar);
-    TEST_TRUE(batch, result, "Delete_Tree() on empty dir");
+    TEST_TRUE(runner, result, "Delete_Tree() on empty dir");
     result = Folder_Delete_Tree(folder, baz);
-    TEST_TRUE(batch, result, "Delete_Tree() on file");
+    TEST_TRUE(runner, result, "Delete_Tree() on file");
 
     // Create new tree to be deleted.
     Folder_MkDir(folder, foo);
@@ -498,17 +492,17 @@ test_Delete_Tree(TestBatch *batch) {
 
     // Remove tree in subdir.
     result = Folder_Delete_Tree(folder, foo_bar);
-    TEST_TRUE(batch, result, "Delete_Tree() of subdir succeeded");
-    TEST_FALSE(batch, Folder_Exists(folder, foo_bar),
+    TEST_TRUE(runner, result, "Delete_Tree() of subdir succeeded");
+    TEST_FALSE(runner, Folder_Exists(folder, foo_bar),
                "subdir really gone");
-    TEST_TRUE(batch, Folder_Exists(folder, foo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo),
               "enclosing dir left intact");
 
     DECREF(folder);
 }
 
 static void
-test_Slurp_File(TestBatch *batch) {
+test_Slurp_File(TestBatchRunner *runner) {
     Folder *folder = (Folder*)RAMFolder_new(NULL);
     FileHandle *fh = Folder_Open_FileHandle(folder, foo,
                                             FH_CREATE | FH_WRITE_ONLY);
@@ -518,28 +512,28 @@ test_Slurp_File(TestBatch *batch) {
     FH_Close(fh);
     DECREF(fh);
     contents = Folder_Slurp_File(folder, foo);
-    TEST_TRUE(batch, BB_Equals_Bytes(contents, "stuff", 5), "Slurp_File");
+    TEST_TRUE(runner, BB_Equals_Bytes(contents, "stuff", 5), "Slurp_File");
 
     DECREF(contents);
     DECREF(folder);
 }
 
 void
-TestFolder_run_tests(TestFolder *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestFolder_run(TestFolder *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 79);
     S_init_strings();
-    test_Exists(batch);
-    test_Set_Path_and_Get_Path(batch);
-    test_MkDir_and_Is_Directory(batch);
-    test_Enclosing_Folder_and_Find_Folder(batch);
-    test_List(batch);
-    test_Open_Dir(batch);
-    test_Open_FileHandle(batch);
-    test_Open_Out(batch);
-    test_Open_In(batch);
-    test_Delete(batch);
-    test_Delete_Tree(batch);
-    test_Slurp_File(batch);
+    test_Exists(runner);
+    test_Set_Path_and_Get_Path(runner);
+    test_MkDir_and_Is_Directory(runner);
+    test_Enclosing_Folder_and_Find_Folder(runner);
+    test_List(runner);
+    test_Open_Dir(runner);
+    test_Open_FileHandle(runner);
+    test_Open_Out(runner);
+    test_Open_In(runner);
+    test_Delete(runner);
+    test_Delete_Tree(runner);
+    test_Slurp_File(runner);
     S_destroy_strings();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolder.cfh b/core/Lucy/Test/Store/TestFolder.cfh
index b9b3bb9..6a5ecf4 100644
--- a/core/Lucy/Test/Store/TestFolder.cfh
+++ b/core/Lucy/Test/Store/TestFolder.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestFolder
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFolder*
-    new(TestFormatter *formatter);
-
-    inert TestFolder*
-    init(TestFolder *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFolder *self);
+    Run(TestFolder *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFolderCommon.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolderCommon.c b/core/Lucy/Test/Store/TestFolderCommon.c
index c2ba9a4..d902bb6 100644
--- a/core/Lucy/Test/Store/TestFolderCommon.c
+++ b/core/Lucy/Test/Store/TestFolderCommon.c
@@ -19,7 +19,7 @@
 
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFolderCommon.h"
-#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Store/Folder.h"
 #include "Lucy/Store/DirHandle.h"
 #include "Lucy/Store/FileHandle.h"
@@ -75,7 +75,7 @@ S_destroy_strings(void) {
 }
 
 static void
-test_Local_Exists(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
+test_Local_Exists(TestBatchRunner *runner, set_up_t set_up, tear_down_t tear_down) {
     Folder *folder = set_up();
     OutStream *outstream = Folder_Open_Out(folder, boffo);
     DECREF(outstream);
@@ -83,13 +83,13 @@ test_Local_Exists(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
     outstream = Folder_Open_Out(folder, foo_boffo);
     DECREF(outstream);
 
-    TEST_TRUE(batch, Folder_Local_Exists(folder, boffo),
+    TEST_TRUE(runner, Folder_Local_Exists(folder, boffo),
               "Local_Exists() returns true for file");
-    TEST_TRUE(batch, Folder_Local_Exists(folder, foo),
+    TEST_TRUE(runner, Folder_Local_Exists(folder, foo),
               "Local_Exists() returns true for dir");
-    TEST_FALSE(batch, Folder_Local_Exists(folder, foo_boffo),
+    TEST_FALSE(runner, Folder_Local_Exists(folder, foo_boffo),
                "Local_Exists() returns false for nested entry");
-    TEST_FALSE(batch, Folder_Local_Exists(folder, bar),
+    TEST_FALSE(runner, Folder_Local_Exists(folder, bar),
                "Local_Exists() returns false for non-existent entry");
 
     Folder_Delete(folder, foo_boffo);
@@ -100,18 +100,18 @@ test_Local_Exists(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
 }
 
 static void
-test_Local_Is_Directory(TestBatch *batch, set_up_t set_up,
+test_Local_Is_Directory(TestBatchRunner *runner, set_up_t set_up,
                         tear_down_t tear_down) {
     Folder *folder = set_up();
     OutStream *outstream = Folder_Open_Out(folder, boffo);
     DECREF(outstream);
     Folder_Local_MkDir(folder, foo);
 
-    TEST_FALSE(batch, Folder_Local_Is_Directory(folder, boffo),
+    TEST_FALSE(runner, Folder_Local_Is_Directory(folder, boffo),
                "Local_Is_Directory() returns false for file");
-    TEST_TRUE(batch, Folder_Local_Is_Directory(folder, foo),
+    TEST_TRUE(runner, Folder_Local_Is_Directory(folder, foo),
               "Local_Is_Directory() returns true for dir");
-    TEST_FALSE(batch, Folder_Local_Is_Directory(folder, bar),
+    TEST_FALSE(runner, Folder_Local_Is_Directory(folder, bar),
                "Local_Is_Directory() returns false for non-existent entry");
 
     Folder_Delete(folder, boffo);
@@ -121,7 +121,7 @@ test_Local_Is_Directory(TestBatch *batch, set_up_t set_up,
 }
 
 static void
-test_Local_Find_Folder(TestBatch *batch, set_up_t set_up,
+test_Local_Find_Folder(TestBatchRunner *runner, set_up_t set_up,
                        tear_down_t tear_down) {
     Folder    *folder = set_up();
     Folder    *local;
@@ -135,26 +135,26 @@ test_Local_Find_Folder(TestBatch *batch, set_up_t set_up,
     DECREF(outstream);
 
     local = Folder_Local_Find_Folder(folder, nope);
-    TEST_TRUE(batch, local == NULL, "Non-existent entry yields NULL");
+    TEST_TRUE(runner, local == NULL, "Non-existent entry yields NULL");
 
     ZombieCharBuf *empty = ZCB_BLANK();
     local = Folder_Local_Find_Folder(folder, (CharBuf*)empty);
-    TEST_TRUE(batch, local == NULL, "Empty string yields NULL");
+    TEST_TRUE(runner, local == NULL, "Empty string yields NULL");
 
     local = Folder_Local_Find_Folder(folder, foo_bar);
-    TEST_TRUE(batch, local == NULL, "nested folder yields NULL");
+    TEST_TRUE(runner, local == NULL, "nested folder yields NULL");
 
     local = Folder_Local_Find_Folder(folder, foo_boffo);
-    TEST_TRUE(batch, local == NULL, "nested file yields NULL");
+    TEST_TRUE(runner, local == NULL, "nested file yields NULL");
 
     local = Folder_Local_Find_Folder(folder, boffo);
-    TEST_TRUE(batch, local == NULL, "local file yields NULL");
+    TEST_TRUE(runner, local == NULL, "local file yields NULL");
 
     local = Folder_Local_Find_Folder(folder, bar);
-    TEST_TRUE(batch, local == NULL, "name of nested folder yields NULL");
+    TEST_TRUE(runner, local == NULL, "name of nested folder yields NULL");
 
     local = Folder_Local_Find_Folder(folder, foo);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               local
               && Folder_Is_A(local, FOLDER)
               && CB_Ends_With(Folder_Get_Path(local), foo),
@@ -169,31 +169,31 @@ test_Local_Find_Folder(TestBatch *batch, set_up_t set_up,
 }
 
 static void
-test_Local_MkDir(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
+test_Local_MkDir(TestBatchRunner *runner, set_up_t set_up, tear_down_t tear_down) {
     Folder *folder = set_up();
     bool result;
 
     result = Folder_Local_MkDir(folder, foo);
-    TEST_TRUE(batch, result, "Local_MkDir succeeds and returns true");
+    TEST_TRUE(runner, result, "Local_MkDir succeeds and returns true");
 
     Err_set_error(NULL);
     result = Folder_Local_MkDir(folder, foo);
-    TEST_FALSE(batch, result,
+    TEST_FALSE(runner, result,
                "Local_MkDir returns false when a dir already exists");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Local_MkDir sets Err_error when a dir already exists");
-    TEST_TRUE(batch, Folder_Exists(folder, foo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo),
               "Existing dir untouched after failed Local_MkDir");
 
     OutStream *outstream = Folder_Open_Out(folder, boffo);
     DECREF(outstream);
     Err_set_error(NULL);
     result = Folder_Local_MkDir(folder, foo);
-    TEST_FALSE(batch, result,
+    TEST_FALSE(runner, result,
                "Local_MkDir returns false when a file already exists");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Local_MkDir sets Err_error when a file already exists");
-    TEST_TRUE(batch, Folder_Exists(folder, boffo) &&
+    TEST_TRUE(runner, Folder_Exists(folder, boffo) &&
               !Folder_Local_Is_Directory(folder, boffo),
               "Existing file untouched after failed Local_MkDir");
 
@@ -204,10 +204,10 @@ test_Local_MkDir(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
 }
 
 static void
-test_Local_Open_Dir(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
+test_Local_Open_Dir(TestBatchRunner *runner, set_up_t set_up, tear_down_t tear_down) {
     Folder *folder = set_up();
     DirHandle *dh = Folder_Local_Open_Dir(folder);
-    TEST_TRUE(batch, dh && DH_Is_A(dh, DIRHANDLE),
+    TEST_TRUE(runner, dh && DH_Is_A(dh, DIRHANDLE),
               "Local_Open_Dir returns an DirHandle");
     DECREF(dh);
     DECREF(folder);
@@ -215,40 +215,40 @@ test_Local_Open_Dir(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
 }
 
 static void
-test_Local_Open_FileHandle(TestBatch *batch, set_up_t set_up,
+test_Local_Open_FileHandle(TestBatchRunner *runner, set_up_t set_up,
                            tear_down_t tear_down) {
     Folder *folder = set_up();
     FileHandle *fh;
 
     fh = Folder_Local_Open_FileHandle(folder, boffo,
                                       FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
-    TEST_TRUE(batch, fh && FH_Is_A(fh, FILEHANDLE),
+    TEST_TRUE(runner, fh && FH_Is_A(fh, FILEHANDLE),
               "opened FileHandle");
     DECREF(fh);
 
     fh = Folder_Local_Open_FileHandle(folder, boffo,
                                       FH_CREATE | FH_WRITE_ONLY);
-    TEST_TRUE(batch, fh && FH_Is_A(fh, FILEHANDLE),
+    TEST_TRUE(runner, fh && FH_Is_A(fh, FILEHANDLE),
               "opened FileHandle for append");
     DECREF(fh);
 
     Err_set_error(NULL);
     fh = Folder_Local_Open_FileHandle(folder, boffo,
                                       FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
-    TEST_TRUE(batch, fh == NULL, "FH_EXLUSIVE flag prevents clobber");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, fh == NULL, "FH_EXLUSIVE flag prevents clobber");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "failure due to FH_EXLUSIVE flag sets Err_error");
 
     fh = Folder_Local_Open_FileHandle(folder, boffo, FH_READ_ONLY);
-    TEST_TRUE(batch, fh && FH_Is_A(fh, FILEHANDLE),
+    TEST_TRUE(runner, fh && FH_Is_A(fh, FILEHANDLE),
               "opened FileHandle for reading");
     DECREF(fh);
 
     Err_set_error(NULL);
     fh = Folder_Local_Open_FileHandle(folder, nope, FH_READ_ONLY);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "Can't open non-existent file for reading");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Opening non-existent file for reading sets Err_error");
 
     Folder_Delete(folder, boffo);
@@ -257,15 +257,15 @@ test_Local_Open_FileHandle(TestBatch *batch, set_up_t set_up,
 }
 
 static void
-test_Local_Delete(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
+test_Local_Delete(TestBatchRunner *runner, set_up_t set_up, tear_down_t tear_down) {
     Folder *folder = set_up();
     OutStream *outstream;
 
     outstream = Folder_Open_Out(folder, boffo);
     DECREF(outstream);
-    TEST_TRUE(batch, Folder_Local_Delete(folder, boffo),
+    TEST_TRUE(runner, Folder_Local_Delete(folder, boffo),
               "Local_Delete on file succeeds");
-    TEST_FALSE(batch, Folder_Exists(folder, boffo),
+    TEST_FALSE(runner, Folder_Exists(folder, boffo),
                "File is really gone");
 
     Folder_Local_MkDir(folder, foo);
@@ -273,13 +273,13 @@ test_Local_Delete(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
     DECREF(outstream);
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, Folder_Local_Delete(folder, foo),
+    TEST_FALSE(runner, Folder_Local_Delete(folder, foo),
                "Local_Delete on non-empty dir fails");
 
     Folder_Delete(folder, foo_boffo);
-    TEST_TRUE(batch, Folder_Local_Delete(folder, foo),
+    TEST_TRUE(runner, Folder_Local_Delete(folder, foo),
               "Local_Delete on empty dir succeeds");
-    TEST_FALSE(batch, Folder_Exists(folder, foo),
+    TEST_FALSE(runner, Folder_Exists(folder, foo),
                "Dir is really gone");
 
     DECREF(folder);
@@ -287,7 +287,7 @@ test_Local_Delete(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
 }
 
 static void
-test_Rename(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
+test_Rename(TestBatchRunner *runner, set_up_t set_up, tear_down_t tear_down) {
     Folder *folder = set_up();
     OutStream *outstream;
     bool result;
@@ -301,24 +301,24 @@ test_Rename(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
     // Move files.
 
     result = Folder_Rename(folder, boffo, banana);
-    TEST_TRUE(batch, result, "Rename succeeds and returns true");
-    TEST_TRUE(batch, Folder_Exists(folder, banana),
+    TEST_TRUE(runner, result, "Rename succeeds and returns true");
+    TEST_TRUE(runner, Folder_Exists(folder, banana),
               "File exists at new path");
-    TEST_FALSE(batch, Folder_Exists(folder, boffo),
+    TEST_FALSE(runner, Folder_Exists(folder, boffo),
                "File no longer exists at old path");
 
     result = Folder_Rename(folder, banana, foo_bar_boffo);
-    TEST_TRUE(batch, result, "Rename to file in nested dir");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_bar_boffo),
+    TEST_TRUE(runner, result, "Rename to file in nested dir");
+    TEST_TRUE(runner, Folder_Exists(folder, foo_bar_boffo),
               "File exists at new path");
-    TEST_FALSE(batch, Folder_Exists(folder, banana),
+    TEST_FALSE(runner, Folder_Exists(folder, banana),
                "File no longer exists at old path");
 
     result = Folder_Rename(folder, foo_bar_boffo, boffo);
-    TEST_TRUE(batch, result, "Rename from file in nested dir");
-    TEST_TRUE(batch, Folder_Exists(folder, boffo),
+    TEST_TRUE(runner, result, "Rename from file in nested dir");
+    TEST_TRUE(runner, Folder_Exists(folder, boffo),
               "File exists at new path");
-    TEST_FALSE(batch, Folder_Exists(folder, foo_bar_boffo),
+    TEST_FALSE(runner, Folder_Exists(folder, foo_bar_boffo),
                "File no longer exists at old path");
 
     outstream = Folder_Open_Out(folder, foo_boffo);
@@ -326,17 +326,17 @@ test_Rename(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
     DECREF(outstream);
     result = Folder_Rename(folder, boffo, foo_boffo);
     if (result) {
-        PASS(batch, "Rename clobbers on this system");
-        TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+        PASS(runner, "Rename clobbers on this system");
+        TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
                   "File exists at new path");
-        TEST_FALSE(batch, Folder_Exists(folder, boffo),
+        TEST_FALSE(runner, Folder_Exists(folder, boffo),
                    "File no longer exists at old path");
     }
     else {
-        PASS(batch, "Rename does not clobber on this system");
-        TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+        PASS(runner, "Rename does not clobber on this system");
+        TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
                   "File exists at new path");
-        TEST_TRUE(batch, Folder_Exists(folder, boffo),
+        TEST_TRUE(runner, Folder_Exists(folder, boffo),
                   "File still exists at old path");
         Folder_Delete(folder, boffo);
     }
@@ -345,74 +345,74 @@ test_Rename(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
 
     Folder_MkDir(folder, baz);
     result = Folder_Rename(folder, baz, boffo);
-    TEST_TRUE(batch, result, "Rename dir");
-    TEST_TRUE(batch, Folder_Exists(folder, boffo),
+    TEST_TRUE(runner, result, "Rename dir");
+    TEST_TRUE(runner, Folder_Exists(folder, boffo),
               "Folder exists at new path");
-    TEST_FALSE(batch, Folder_Exists(folder, baz),
+    TEST_FALSE(runner, Folder_Exists(folder, baz),
                "Folder no longer exists at old path");
 
     result = Folder_Rename(folder, boffo, foo_foo);
-    TEST_TRUE(batch, result, "Rename dir into nested subdir");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_foo),
+    TEST_TRUE(runner, result, "Rename dir into nested subdir");
+    TEST_TRUE(runner, Folder_Exists(folder, foo_foo),
               "Folder exists at new path");
-    TEST_FALSE(batch, Folder_Exists(folder, boffo),
+    TEST_FALSE(runner, Folder_Exists(folder, boffo),
                "Folder no longer exists at old path");
 
     result = Folder_Rename(folder, foo_foo, foo_bar_baz);
-    TEST_TRUE(batch, result, "Rename dir from nested subdir");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_bar_baz),
+    TEST_TRUE(runner, result, "Rename dir from nested subdir");
+    TEST_TRUE(runner, Folder_Exists(folder, foo_bar_baz),
               "Folder exists at new path");
-    TEST_FALSE(batch, Folder_Exists(folder, foo_foo),
+    TEST_FALSE(runner, Folder_Exists(folder, foo_foo),
                "Folder no longer exists at old path");
 
     // Test failed clobbers.
 
     Err_set_error(NULL);
     result = Folder_Rename(folder, foo_boffo, foo_bar);
-    TEST_FALSE(batch, result, "Rename file clobbering dir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Rename file clobbering dir fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Failed rename sets Err_error");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "File still exists at old path");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_bar),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_bar),
               "Dir still exists after failed clobber");
 
     Err_set_error(NULL);
     result = Folder_Rename(folder, foo_bar, foo_boffo);
-    TEST_FALSE(batch, result, "Rename dir clobbering file fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Rename dir clobbering file fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Failed rename sets Err_error");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_bar),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_bar),
               "Dir still exists at old path");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "File still exists after failed clobber");
 
     // Test that "renaming" succeeds where to and from are the same.
 
     result = Folder_Rename(folder, foo_boffo, foo_boffo);
-    TEST_TRUE(batch, result, "Renaming file to itself succeeds");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, result, "Renaming file to itself succeeds");
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "File still exists");
 
     result = Folder_Rename(folder, foo_bar, foo_bar);
-    TEST_TRUE(batch, result, "Renaming dir to itself succeeds");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_bar),
+    TEST_TRUE(runner, result, "Renaming dir to itself succeeds");
+    TEST_TRUE(runner, Folder_Exists(folder, foo_bar),
               "Dir still exists");
 
     // Invalid filepaths.
 
     Err_set_error(NULL);
     result = Folder_Rename(folder, foo_boffo, nope_nyet);
-    TEST_FALSE(batch, result, "Rename into non-existent subdir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Rename into non-existent subdir fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Renaming into non-existent subdir sets Err_error");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "Entry still exists at old path");
 
     Err_set_error(NULL);
     result = Folder_Rename(folder, nope_nyet, boffo);
-    TEST_FALSE(batch, result, "Rename non-existent file fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Rename non-existent file fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Renaming non-existent source file sets Err_error");
 
     Folder_Delete(folder, foo_bar_baz);
@@ -424,7 +424,7 @@ test_Rename(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
 }
 
 static void
-test_Hard_Link(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
+test_Hard_Link(TestBatchRunner *runner, set_up_t set_up, tear_down_t tear_down) {
     Folder *folder = set_up();
     OutStream *outstream;
     bool result;
@@ -437,26 +437,26 @@ test_Hard_Link(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
     // Link files.
 
     result = Folder_Hard_Link(folder, boffo, banana);
-    TEST_TRUE(batch, result, "Hard_Link succeeds and returns true");
-    TEST_TRUE(batch, Folder_Exists(folder, banana),
+    TEST_TRUE(runner, result, "Hard_Link succeeds and returns true");
+    TEST_TRUE(runner, Folder_Exists(folder, banana),
               "File exists at new path");
-    TEST_TRUE(batch, Folder_Exists(folder, boffo),
+    TEST_TRUE(runner, Folder_Exists(folder, boffo),
               "File still exists at old path");
     Folder_Delete(folder, boffo);
 
     result = Folder_Hard_Link(folder, banana, foo_bar_boffo);
-    TEST_TRUE(batch, result, "Hard_Link to target within nested dir");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_bar_boffo),
+    TEST_TRUE(runner, result, "Hard_Link to target within nested dir");
+    TEST_TRUE(runner, Folder_Exists(folder, foo_bar_boffo),
               "File exists at new path");
-    TEST_TRUE(batch, Folder_Exists(folder, banana),
+    TEST_TRUE(runner, Folder_Exists(folder, banana),
               "File still exists at old path");
     Folder_Delete(folder, banana);
 
     result = Folder_Hard_Link(folder, foo_bar_boffo, foo_boffo);
-    TEST_TRUE(batch, result, "Hard_Link from file in nested dir");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, result, "Hard_Link from file in nested dir");
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "File exists at new path");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_bar_boffo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_bar_boffo),
               "File still exists at old path");
     Folder_Delete(folder, foo_bar_boffo);
 
@@ -465,19 +465,19 @@ test_Hard_Link(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
     outstream = Folder_Open_Out(folder, boffo);
     DECREF(outstream);
     result = Folder_Hard_Link(folder, foo_boffo, boffo);
-    TEST_FALSE(batch, result, "Clobber of file fails");
-    TEST_TRUE(batch, Folder_Exists(folder, boffo),
+    TEST_FALSE(runner, result, "Clobber of file fails");
+    TEST_TRUE(runner, Folder_Exists(folder, boffo),
               "File still exists at new path");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "File still exists at old path");
     Folder_Delete(folder, boffo);
 
     Folder_MkDir(folder, baz);
     result = Folder_Hard_Link(folder, foo_boffo, baz);
-    TEST_FALSE(batch, result, "Clobber of dir fails");
-    TEST_TRUE(batch, Folder_Exists(folder, baz),
+    TEST_FALSE(runner, result, "Clobber of dir fails");
+    TEST_TRUE(runner, Folder_Exists(folder, baz),
               "Dir still exists at new path");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "File still exists at old path");
     Folder_Delete(folder, baz);
 
@@ -485,34 +485,34 @@ test_Hard_Link(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
 
     Folder_MkDir(folder, baz);
     result = Folder_Hard_Link(folder, baz, banana);
-    TEST_FALSE(batch, result, "Hard_Link dir fails");
-    TEST_FALSE(batch, Folder_Exists(folder, banana),
+    TEST_FALSE(runner, result, "Hard_Link dir fails");
+    TEST_FALSE(runner, Folder_Exists(folder, banana),
                "Nothing at new path");
-    TEST_TRUE(batch, Folder_Exists(folder, baz),
+    TEST_TRUE(runner, Folder_Exists(folder, baz),
               "Folder still exists at old path");
     Folder_Delete(folder, baz);
 
     // Test that linking to yourself fails.
 
     result = Folder_Hard_Link(folder, foo_boffo, foo_boffo);
-    TEST_FALSE(batch, result, "Hard_Link file to itself fails");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_FALSE(runner, result, "Hard_Link file to itself fails");
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "File still exists");
 
     // Invalid filepaths.
 
     Err_set_error(NULL);
     result = Folder_Rename(folder, foo_boffo, nope_nyet);
-    TEST_FALSE(batch, result, "Hard_Link into non-existent subdir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Hard_Link into non-existent subdir fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Hard_Link into non-existent subdir sets Err_error");
-    TEST_TRUE(batch, Folder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, Folder_Exists(folder, foo_boffo),
               "Entry still exists at old path");
 
     Err_set_error(NULL);
     result = Folder_Rename(folder, nope_nyet, boffo);
-    TEST_FALSE(batch, result, "Hard_Link non-existent source file fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Hard_Link non-existent source file fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Hard_Link non-existent source file sets Err_error");
 
     Folder_Delete(folder, foo_bar);
@@ -523,13 +523,13 @@ test_Hard_Link(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
 }
 
 static void
-test_Close(TestBatch *batch, set_up_t set_up, tear_down_t tear_down) {
+test_Close(TestBatchRunner *runner, set_up_t set_up, tear_down_t tear_down) {
     Folder *folder = set_up();
     Folder_Close(folder);
-    PASS(batch, "Close() concludes without incident");
+    PASS(runner, "Close() concludes without incident");
     Folder_Close(folder);
     Folder_Close(folder);
-    PASS(batch, "Calling Close() multiple times is safe");
+    PASS(runner, "Calling Close() multiple times is safe");
     DECREF(folder);
     tear_down();
 }
@@ -540,21 +540,19 @@ TestFolderCommon_num_tests() {
 }
 
 void
-TestFolderCommon_run_tests(void *test_batch, set_up_t set_up,
+TestFolderCommon_run_tests(TestBatchRunner *runner, set_up_t set_up,
                            tear_down_t tear_down) {
-    TestBatch *batch = (TestBatch*)test_batch;
-
     S_init_strings();
-    test_Local_Exists(batch, set_up, tear_down);
-    test_Local_Is_Directory(batch, set_up, tear_down);
-    test_Local_Find_Folder(batch, set_up, tear_down);
-    test_Local_MkDir(batch, set_up, tear_down);
-    test_Local_Open_Dir(batch, set_up, tear_down);
-    test_Local_Open_FileHandle(batch, set_up, tear_down);
-    test_Local_Delete(batch, set_up, tear_down);
-    test_Rename(batch, set_up, tear_down);
-    test_Hard_Link(batch, set_up, tear_down);
-    test_Close(batch, set_up, tear_down);
+    test_Local_Exists(runner, set_up, tear_down);
+    test_Local_Is_Directory(runner, set_up, tear_down);
+    test_Local_Find_Folder(runner, set_up, tear_down);
+    test_Local_MkDir(runner, set_up, tear_down);
+    test_Local_Open_Dir(runner, set_up, tear_down);
+    test_Local_Open_FileHandle(runner, set_up, tear_down);
+    test_Local_Delete(runner, set_up, tear_down);
+    test_Rename(runner, set_up, tear_down);
+    test_Hard_Link(runner, set_up, tear_down);
+    test_Close(runner, set_up, tear_down);
     S_destroy_strings();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFolderCommon.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolderCommon.cfh b/core/Lucy/Test/Store/TestFolderCommon.cfh
index f072ce9..e75dce4 100644
--- a/core/Lucy/Test/Store/TestFolderCommon.cfh
+++ b/core/Lucy/Test/Store/TestFolderCommon.cfh
@@ -32,7 +32,7 @@ inert class Lucy::Test::Store::TestFolderCommon {
     num_tests();
 
     inert void
-    run_tests(void *test_batch,
+    run_tests(TestBatchRunner *runner,
               Lucy_TestFolderCommon_Set_Up_t set_up,
               Lucy_TestFolderCommon_Tear_Down_t tear_down);
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestIOChunks.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOChunks.c b/core/Lucy/Test/Store/TestIOChunks.c
index cbf4f10..fe2fc61 100644
--- a/core/Lucy/Test/Store/TestIOChunks.c
+++ b/core/Lucy/Test/Store/TestIOChunks.c
@@ -22,7 +22,7 @@
 
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
@@ -34,25 +34,19 @@
 #include "Clownfish/Util/NumberUtils.h"
 
 TestIOChunks*
-TestIOChunks_new(TestFormatter *formatter) {
-    TestIOChunks *self = (TestIOChunks*)VTable_Make_Obj(TESTIOCHUNKS);
-    return TestIOChunks_init(self, formatter);
-}
-
-TestIOChunks*
-TestIOChunks_init(TestIOChunks *self, TestFormatter *formatter) {
-    return (TestIOChunks*)TestBatch_init((TestBatch*)self, 36, formatter);
+TestIOChunks_new() {
+    return (TestIOChunks*)VTable_Make_Obj(TESTIOCHUNKS);
 }
 
 static void
-test_Align(TestBatch *batch) {
+test_Align(TestBatchRunner *runner) {
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
 
     for (int32_t i = 1; i < 32; i++) {
         int64_t random_bytes = TestUtils_random_u64() % 32;
         while (random_bytes--) { OutStream_Write_U8(outstream, 0); }
-        TEST_TRUE(batch, (OutStream_Align(outstream, i) % i) == 0,
+        TEST_TRUE(runner, (OutStream_Align(outstream, i) % i) == 0,
                   "Align to %ld", (long)i);
     }
     DECREF(file);
@@ -60,7 +54,7 @@ test_Align(TestBatch *batch) {
 }
 
 static void
-test_Read_Write_Bytes(TestBatch *batch) {
+test_Read_Write_Bytes(TestBatchRunner *runner) {
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
     InStream   *instream;
@@ -71,7 +65,7 @@ test_Read_Write_Bytes(TestBatch *batch) {
 
     instream = InStream_open((Obj*)file);
     InStream_Read_Bytes(instream, buf, 4);
-    TEST_TRUE(batch, strcmp(buf, "foo") == 0, "Read_Bytes Write_Bytes");
+    TEST_TRUE(runner, strcmp(buf, "foo") == 0, "Read_Bytes Write_Bytes");
 
     DECREF(instream);
     DECREF(outstream);
@@ -79,7 +73,7 @@ test_Read_Write_Bytes(TestBatch *batch) {
 }
 
 static void
-test_Buf(TestBatch *batch) {
+test_Buf(TestBatchRunner *runner) {
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
     size_t      size      = IO_STREAM_BUF_SIZE * 2 + 5;
@@ -93,24 +87,24 @@ test_Buf(TestBatch *batch) {
 
     instream = InStream_open((Obj*)file);
     buf = InStream_Buf(instream, 5);
-    TEST_INT_EQ(batch, instream->limit - buf, IO_STREAM_BUF_SIZE,
+    TEST_INT_EQ(runner, instream->limit - buf, IO_STREAM_BUF_SIZE,
                 "Small request bumped up");
 
     buf += IO_STREAM_BUF_SIZE - 10; // 10 bytes left in buffer.
     InStream_Advance_Buf(instream, buf);
 
     buf = InStream_Buf(instream, 10);
-    TEST_INT_EQ(batch, instream->limit - buf, 10,
+    TEST_INT_EQ(runner, instream->limit - buf, 10,
                 "Exact request doesn't trigger refill");
 
     buf = InStream_Buf(instream, 11);
-    TEST_INT_EQ(batch, instream->limit - buf, IO_STREAM_BUF_SIZE,
+    TEST_INT_EQ(runner, instream->limit - buf, IO_STREAM_BUF_SIZE,
                 "Requesting over limit triggers refill");
 
     int64_t  expected = InStream_Length(instream) - InStream_Tell(instream);
     char    *buff     = InStream_Buf(instream, 100000);
     int64_t  got      = PTR_TO_I64(instream->limit) - PTR_TO_I64(buff);
-    TEST_TRUE(batch, got == expected,
+    TEST_TRUE(runner, got == expected,
               "Requests greater than file size get pared down");
 
     DECREF(instream);
@@ -119,12 +113,12 @@ test_Buf(TestBatch *batch) {
 }
 
 void
-TestIOChunks_run_tests(TestIOChunks *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestIOChunks_run(TestIOChunks *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 36);
     srand((unsigned int)time((time_t*)NULL));
-    test_Align(batch);
-    test_Read_Write_Bytes(batch);
-    test_Buf(batch);
+    test_Align(runner);
+    test_Read_Write_Bytes(runner);
+    test_Buf(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestIOChunks.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOChunks.cfh b/core/Lucy/Test/Store/TestIOChunks.cfh
index 1cae6a9..68c459a 100644
--- a/core/Lucy/Test/Store/TestIOChunks.cfh
+++ b/core/Lucy/Test/Store/TestIOChunks.cfh
@@ -22,13 +22,10 @@ class Lucy::Test::Store::TestIOChunks
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestIOChunks*
-    new(TestFormatter *formatter);
-
-    inert TestIOChunks*
-    init(TestIOChunks *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestIOChunks *self);
+    Run(TestIOChunks *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestIOPrimitives.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOPrimitives.c b/core/Lucy/Test/Store/TestIOPrimitives.c
index 38635d8..95565f5 100644
--- a/core/Lucy/Test/Store/TestIOPrimitives.c
+++ b/core/Lucy/Test/Store/TestIOPrimitives.c
@@ -22,7 +22,7 @@
 
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
@@ -34,18 +34,12 @@
 #include "Clownfish/Util/NumberUtils.h"
 
 TestIOPrimitives*
-TestIOPrimitives_new(TestFormatter *formatter) {
-    TestIOPrimitives *self = (TestIOPrimitives*)VTable_Make_Obj(TESTIOPRIMITIVES);
-    return TestIOPrimitives_init(self, formatter);
-}
-
-TestIOPrimitives*
-TestIOPrimitives_init(TestIOPrimitives *self, TestFormatter *formatter) {
-    return (TestIOPrimitives*)TestBatch_init((TestBatch*)self, 11, formatter);
+TestIOPrimitives_new() {
+    return (TestIOPrimitives*)VTable_Make_Obj(TESTIOPRIMITIVES);
 }
 
 static void
-test_i8(TestBatch *batch) {
+test_i8(TestBatchRunner *runner) {
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
     InStream   *instream;
@@ -60,7 +54,7 @@ test_i8(TestBatch *batch) {
     for (i = -128; i < 128; i++) {
         if (InStream_Read_I8(instream) != i) { break; }
     }
-    TEST_INT_EQ(batch, i, 128, "round trip i8 successful for %d out of 256",
+    TEST_INT_EQ(runner, i, 128, "round trip i8 successful for %d out of 256",
                 i + 128);
 
     DECREF(instream);
@@ -69,7 +63,7 @@ test_i8(TestBatch *batch) {
 }
 
 static void
-test_u8(TestBatch *batch) {
+test_u8(TestBatchRunner *runner) {
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
     InStream   *instream;
@@ -84,7 +78,7 @@ test_u8(TestBatch *batch) {
     for (i = 0; i < 256; i++) {
         if (InStream_Read_U8(instream) != i) { break; }
     }
-    TEST_INT_EQ(batch, i, 256,
+    TEST_INT_EQ(runner, i, 256,
                 "round trip u8 successful for %d out of 256", i);
 
     DECREF(instream);
@@ -93,7 +87,7 @@ test_u8(TestBatch *batch) {
 }
 
 static void
-test_i32(TestBatch *batch) {
+test_i32(TestBatchRunner *runner) {
     int64_t    *ints = TestUtils_random_i64s(NULL, 1000, INT32_MIN, INT32_MAX);
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
@@ -115,13 +109,13 @@ test_i32(TestBatch *batch) {
     for (i = 0; i < 1000; i++) {
         int32_t got = InStream_Read_I32(instream);
         if (got != ints[i]) {
-            FAIL(batch, "i32 round trip failed: %ld, %ld", (long)got,
+            FAIL(runner, "i32 round trip failed: %ld, %ld", (long)got,
                  (long)ints[i]);
             break;
         }
     }
     if (i == 1000) {
-        PASS(batch, "i32 round trip");
+        PASS(runner, "i32 round trip");
     }
 
     DECREF(instream);
@@ -131,7 +125,7 @@ test_i32(TestBatch *batch) {
 }
 
 static void
-test_u32(TestBatch *batch) {
+test_u32(TestBatchRunner *runner) {
     uint64_t   *ints = TestUtils_random_u64s(NULL, 1000, 0, UINT32_MAX);
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
@@ -153,13 +147,13 @@ test_u32(TestBatch *batch) {
     for (i = 0; i < 1000; i++) {
         uint32_t got = InStream_Read_U32(instream);
         if (got != ints[i]) {
-            FAIL(batch, "u32 round trip failed: %lu, %lu", (unsigned long)got,
+            FAIL(runner, "u32 round trip failed: %lu, %lu", (unsigned long)got,
                  (unsigned long)ints[i]);
             break;
         }
     }
     if (i == 1000) {
-        PASS(batch, "u32 round trip");
+        PASS(runner, "u32 round trip");
     }
 
     DECREF(instream);
@@ -169,7 +163,7 @@ test_u32(TestBatch *batch) {
 }
 
 static void
-test_i64(TestBatch *batch) {
+test_i64(TestBatchRunner *runner) {
     int64_t    *ints = TestUtils_random_i64s(NULL, 1000, INT64_MIN, INT64_MAX);
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
@@ -191,13 +185,13 @@ test_i64(TestBatch *batch) {
     for (i = 0; i < 1000; i++) {
         int64_t got = InStream_Read_I64(instream);
         if (got != ints[i]) {
-            FAIL(batch, "i64 round trip failed: %" PRId64 ", %" PRId64,
+            FAIL(runner, "i64 round trip failed: %" PRId64 ", %" PRId64,
                  got, ints[i]);
             break;
         }
     }
     if (i == 1000) {
-        PASS(batch, "i64 round trip");
+        PASS(runner, "i64 round trip");
     }
 
     DECREF(instream);
@@ -208,7 +202,7 @@ test_i64(TestBatch *batch) {
 
 
 static void
-test_u64(TestBatch *batch) {
+test_u64(TestBatchRunner *runner) {
     uint64_t   *ints = TestUtils_random_u64s(NULL, 1000, 0, UINT64_MAX);
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
@@ -230,13 +224,13 @@ test_u64(TestBatch *batch) {
     for (i = 0; i < 1000; i++) {
         uint64_t got = InStream_Read_U64(instream);
         if (got != ints[i]) {
-            FAIL(batch, "u64 round trip failed: %" PRIu64 ", %" PRIu64,
+            FAIL(runner, "u64 round trip failed: %" PRIu64 ", %" PRIu64,
                  got, ints[i]);
             break;
         }
     }
     if (i == 1000) {
-        PASS(batch, "u64 round trip");
+        PASS(runner, "u64 round trip");
     }
 
     DECREF(instream);
@@ -246,7 +240,7 @@ test_u64(TestBatch *batch) {
 }
 
 static void
-test_c32(TestBatch *batch) {
+test_c32(TestBatchRunner *runner) {
     uint64_t   *ints = TestUtils_random_u64s(NULL, 1000, 0, UINT32_MAX);
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
@@ -268,13 +262,13 @@ test_c32(TestBatch *batch) {
     for (i = 0; i < 1000; i++) {
         uint32_t got = InStream_Read_C32(instream);
         if (got != ints[i]) {
-            FAIL(batch, "c32 round trip failed: %lu, %lu", (unsigned long)got,
+            FAIL(runner, "c32 round trip failed: %lu, %lu", (unsigned long)got,
                  (unsigned long)ints[i]);
             break;
         }
     }
     if (i == 1000) {
-        PASS(batch, "c32 round trip");
+        PASS(runner, "c32 round trip");
     }
 
     DECREF(instream);
@@ -284,7 +278,7 @@ test_c32(TestBatch *batch) {
 }
 
 static void
-test_c64(TestBatch *batch) {
+test_c64(TestBatchRunner *runner) {
     uint64_t   *ints   = TestUtils_random_u64s(NULL, 1000, 0, UINT64_MAX);
     RAMFile    *file     = RAMFile_new(NULL, false);
     RAMFile    *raw_file = RAMFile_new(NULL, false);
@@ -311,13 +305,13 @@ test_c64(TestBatch *batch) {
     for (i = 0; i < 1000; i++) {
         uint64_t got = InStream_Read_C64(instream);
         if (got != ints[i]) {
-            FAIL(batch, "c64 round trip failed: %" PRIu64 ", %" PRIu64,
+            FAIL(runner, "c64 round trip failed: %" PRIu64 ", %" PRIu64,
                  got, ints[i]);
             break;
         }
     }
     if (i == 1000) {
-        PASS(batch, "c64 round trip");
+        PASS(runner, "c64 round trip");
     }
 
     raw_instream = InStream_open((Obj*)raw_file);
@@ -328,13 +322,13 @@ test_c64(TestBatch *batch) {
         uint64_t got = NumUtil_decode_c64(&buf);
         UNUSED_VAR(size);
         if (got != ints[i]) {
-            FAIL(batch, "Read_Raw_C64 failed: %" PRIu64 ", %" PRIu64,
+            FAIL(runner, "Read_Raw_C64 failed: %" PRIu64 ", %" PRIu64,
                  got, ints[i]);
             break;
         }
     }
     if (i == 1000) {
-        PASS(batch, "Read_Raw_C64");
+        PASS(runner, "Read_Raw_C64");
     }
 
     DECREF(raw_instream);
@@ -347,7 +341,7 @@ test_c64(TestBatch *batch) {
 }
 
 static void
-test_f32(TestBatch *batch) {
+test_f32(TestBatchRunner *runner) {
     double     *f64s   = TestUtils_random_f64s(NULL, 1000);
     float      *values = (float*)MALLOCATE(1000 * sizeof(float));
     RAMFile    *file      = RAMFile_new(NULL, false);
@@ -373,12 +367,12 @@ test_f32(TestBatch *batch) {
     for (i = 0; i < 1000; i++) {
         float got = InStream_Read_F32(instream);
         if (got != values[i]) {
-            FAIL(batch, "f32 round trip failed: %f, %f", got, values[i]);
+            FAIL(runner, "f32 round trip failed: %f, %f", got, values[i]);
             break;
         }
     }
     if (i == 1000) {
-        PASS(batch, "f32 round trip");
+        PASS(runner, "f32 round trip");
     }
 
     DECREF(instream);
@@ -389,7 +383,7 @@ test_f32(TestBatch *batch) {
 }
 
 static void
-test_f64(TestBatch *batch) {
+test_f64(TestBatchRunner *runner) {
     double     *values = TestUtils_random_f64s(NULL, 1000);
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
@@ -409,12 +403,12 @@ test_f64(TestBatch *batch) {
     for (i = 0; i < 1000; i++) {
         double got = InStream_Read_F64(instream);
         if (got != values[i]) {
-            FAIL(batch, "f64 round trip failed: %f, %f", got, values[i]);
+            FAIL(runner, "f64 round trip failed: %f, %f", got, values[i]);
             break;
         }
     }
     if (i == 1000) {
-        PASS(batch, "f64 round trip");
+        PASS(runner, "f64 round trip");
     }
 
     DECREF(instream);
@@ -424,19 +418,19 @@ test_f64(TestBatch *batch) {
 }
 
 void
-TestIOPrimitives_run_tests(TestIOPrimitives *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestIOPrimitives_run(TestIOPrimitives *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 11);
     srand((unsigned int)time((time_t*)NULL));
-    test_i8(batch);
-    test_u8(batch);
-    test_i32(batch);
-    test_u32(batch);
-    test_i64(batch);
-    test_u64(batch);
-    test_c32(batch);
-    test_c64(batch);
-    test_f32(batch);
-    test_f64(batch);
+    test_i8(runner);
+    test_u8(runner);
+    test_i32(runner);
+    test_u32(runner);
+    test_i64(runner);
+    test_u64(runner);
+    test_c32(runner);
+    test_c64(runner);
+    test_f32(runner);
+    test_f64(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestIOPrimitives.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOPrimitives.cfh b/core/Lucy/Test/Store/TestIOPrimitives.cfh
index ddf7852..c75419a 100644
--- a/core/Lucy/Test/Store/TestIOPrimitives.cfh
+++ b/core/Lucy/Test/Store/TestIOPrimitives.cfh
@@ -22,13 +22,10 @@ class Lucy::Test::Store::TestIOPrimitives
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestIOPrimitives*
-    new(TestFormatter *formatter);
-
-    inert TestIOPrimitives*
-    init(TestIOPrimitives *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestIOPrimitives *self);
+    Run(TestIOPrimitives *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestInStream.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestInStream.c b/core/Lucy/Test/Store/TestInStream.c
index 9a29002..a09df9f 100644
--- a/core/Lucy/Test/Store/TestInStream.c
+++ b/core/Lucy/Test/Store/TestInStream.c
@@ -20,7 +20,7 @@
 
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Store/TestInStream.h"
@@ -33,18 +33,12 @@
 #include "Clownfish/Util/NumberUtils.h"
 
 TestInStream*
-TestInStream_new(TestFormatter *formatter) {
-    TestInStream *self = (TestInStream*)VTable_Make_Obj(TESTINSTREAM);
-    return TestInStream_init(self, formatter);
-}
-
-TestInStream*
-TestInStream_init(TestInStream *self, TestFormatter *formatter) {
-    return (TestInStream*)TestBatch_init((TestBatch*)self, 37, formatter);
+TestInStream_new() {
+    return (TestInStream*)VTable_Make_Obj(TESTINSTREAM);
 }
 
 static void
-test_refill(TestBatch *batch) {
+test_refill(TestBatchRunner *runner) {
     RAMFile    *file      = RAMFile_new(NULL, false);
     OutStream  *outstream = OutStream_open((Obj*)file);
     InStream   *instream;
@@ -59,35 +53,35 @@ test_refill(TestBatch *batch) {
 
     instream = InStream_open((Obj*)file);
     InStream_Refill(instream);
-    TEST_INT_EQ(batch, instream->limit - instream->buf, IO_STREAM_BUF_SIZE,
+    TEST_INT_EQ(runner, instream->limit - instream->buf, IO_STREAM_BUF_SIZE,
                 "Refill");
-    TEST_INT_EQ(batch, (long)InStream_Tell(instream), 0,
+    TEST_INT_EQ(runner, (long)InStream_Tell(instream), 0,
                 "Correct file pos after standing-start Refill()");
     DECREF(instream);
 
     instream = InStream_open((Obj*)file);
     InStream_Fill(instream, 30);
-    TEST_INT_EQ(batch, instream->limit - instream->buf, 30, "Fill()");
-    TEST_INT_EQ(batch, (long)InStream_Tell(instream), 0,
+    TEST_INT_EQ(runner, instream->limit - instream->buf, 30, "Fill()");
+    TEST_INT_EQ(runner, (long)InStream_Tell(instream), 0,
                 "Correct file pos after standing-start Fill()");
     DECREF(instream);
 
     instream = InStream_open((Obj*)file);
     InStream_Read_Bytes(instream, scratch, 5);
-    TEST_INT_EQ(batch, instream->limit - instream->buf,
+    TEST_INT_EQ(runner, instream->limit - instream->buf,
                 IO_STREAM_BUF_SIZE - 5, "small read triggers refill");
     DECREF(instream);
 
     instream = InStream_open((Obj*)file);
-    TEST_INT_EQ(batch, InStream_Read_U8(instream), 'x', "Read_U8");
+    TEST_INT_EQ(runner, InStream_Read_U8(instream), 'x', "Read_U8");
     InStream_Seek(instream, 1023);
-    TEST_INT_EQ(batch, (long)instream->window->offset, 0,
+    TEST_INT_EQ(runner, (long)instream->window->offset, 0,
                 "no unnecessary refill on Seek");
-    TEST_INT_EQ(batch, (long)InStream_Tell(instream), 1023, "Seek/Tell");
-    TEST_INT_EQ(batch, InStream_Read_U8(instream), 'y',
+    TEST_INT_EQ(runner, (long)InStream_Tell(instream), 1023, "Seek/Tell");
+    TEST_INT_EQ(runner, InStream_Read_U8(instream), 'y',
                 "correct data after in-buffer Seek()");
-    TEST_INT_EQ(batch, InStream_Read_U8(instream), 'z', "automatic Refill");
-    TEST_TRUE(batch, (instream->window->offset != 0), "refilled");
+    TEST_INT_EQ(runner, InStream_Read_U8(instream), 'z', "automatic Refill");
+    TEST_TRUE(runner, (instream->window->offset != 0), "refilled");
 
     DECREF(instream);
     DECREF(outstream);
@@ -95,7 +89,7 @@ test_refill(TestBatch *batch) {
 }
 
 static void
-test_Clone_and_Reopen(TestBatch *batch) {
+test_Clone_and_Reopen(TestBatchRunner *runner) {
     ZombieCharBuf *foo       = ZCB_WRAP_STR("foo", 3);
     ZombieCharBuf *bar       = ZCB_WRAP_STR("bar", 3);
     RAMFile       *file      = RAMFile_new(NULL, false);
@@ -113,28 +107,28 @@ test_Clone_and_Reopen(TestBatch *batch) {
     fh = RAMFH_open((CharBuf*)foo, FH_READ_ONLY, file);
     instream = InStream_open((Obj*)fh);
     InStream_Seek(instream, 1);
-    TEST_TRUE(batch, CB_Equals(InStream_Get_Filename(instream), (Obj*)foo),
+    TEST_TRUE(runner, CB_Equals(InStream_Get_Filename(instream), (Obj*)foo),
               "Get_Filename");
 
     clone    = InStream_Clone(instream);
-    TEST_TRUE(batch, CB_Equals(InStream_Get_Filename(clone), (Obj*)foo),
+    TEST_TRUE(runner, CB_Equals(InStream_Get_Filename(clone), (Obj*)foo),
               "Clones have same filename");
-    TEST_TRUE(batch, InStream_Length(instream) == InStream_Length(clone),
+    TEST_TRUE(runner, InStream_Length(instream) == InStream_Length(clone),
               "Clones have same length");
-    TEST_TRUE(batch, InStream_Read_U8(instream) == InStream_Read_U8(clone),
+    TEST_TRUE(runner, InStream_Read_U8(instream) == InStream_Read_U8(clone),
               "Clones start at same file position");
 
     reopened = InStream_Reopen(instream, (CharBuf*)bar, 25, 1);
-    TEST_TRUE(batch, CB_Equals(InStream_Get_Filename(reopened), (Obj*)bar),
+    TEST_TRUE(runner, CB_Equals(InStream_Get_Filename(reopened), (Obj*)bar),
               "Reopened InStreams take new filename");
-    TEST_TRUE(batch, InStream_Read_U8(reopened) == 'z',
+    TEST_TRUE(runner, InStream_Read_U8(reopened) == 'z',
               "Reopened stream starts at supplied offset");
-    TEST_TRUE(batch, InStream_Length(reopened) == 1,
+    TEST_TRUE(runner, InStream_Length(reopened) == 1,
               "Reopened stream uses supplied length");
-    TEST_TRUE(batch, InStream_Tell(reopened) == 1,
+    TEST_TRUE(runner, InStream_Tell(reopened) == 1,
               "Tell() uses supplied offset for reopened stream");
     InStream_Seek(reopened, 0);
-    TEST_TRUE(batch, InStream_Read_U8(reopened) == 'z',
+    TEST_TRUE(runner, InStream_Read_U8(reopened) == 'z',
               "Seek() uses supplied offset for reopened stream");
 
     DECREF(reopened);
@@ -146,18 +140,18 @@ test_Clone_and_Reopen(TestBatch *batch) {
 }
 
 static void
-test_Close(TestBatch *batch) {
+test_Close(TestBatchRunner *runner) {
     RAMFile  *file     = RAMFile_new(NULL, false);
     InStream *instream = InStream_open((Obj*)file);
     InStream_Close(instream);
-    TEST_TRUE(batch, instream->file_handle == NULL,
+    TEST_TRUE(runner, instream->file_handle == NULL,
               "Close decrements FileHandle's refcount");
     DECREF(instream);
     DECREF(file);
 }
 
 static void
-test_Seek_and_Tell(TestBatch *batch) {
+test_Seek_and_Tell(TestBatchRunner *runner) {
     int64_t     gb1      = INT64_C(0x40000000);
     int64_t     gb3      = gb1 * 3;
     int64_t     gb6      = gb1 * 6;
@@ -166,47 +160,47 @@ test_Seek_and_Tell(TestBatch *batch) {
     InStream   *instream = InStream_open((Obj*)fh);
 
     InStream_Buf(instream, 10000);
-    TEST_TRUE(batch, instream->limit == ((char*)NULL) + 10000,
+    TEST_TRUE(runner, instream->limit == ((char*)NULL) + 10000,
               "InStream_Buf sets limit");
 
     InStream_Seek(instream, gb6);
-    TEST_TRUE(batch, InStream_Tell(instream) == gb6,
+    TEST_TRUE(runner, InStream_Tell(instream) == gb6,
               "Tell after seek forwards outside buffer");
-    TEST_TRUE(batch, instream->buf == NULL,
+    TEST_TRUE(runner, instream->buf == NULL,
               "Seek forwards outside buffer sets buf to NULL");
-    TEST_TRUE(batch, instream->limit == NULL,
+    TEST_TRUE(runner, instream->limit == NULL,
               "Seek forwards outside buffer sets limit to NULL");
-    TEST_TRUE(batch, instream->window->offset == gb6,
+    TEST_TRUE(runner, instream->window->offset == gb6,
               "Seek forwards outside buffer tracks pos in window offset");
 
     InStream_Buf(instream, (size_t)gb1);
-    TEST_TRUE(batch, instream->limit == ((char*)NULL) + gb1,
+    TEST_TRUE(runner, instream->limit == ((char*)NULL) + gb1,
               "InStream_Buf sets limit");
 
     InStream_Seek(instream, gb6 + 10);
-    TEST_TRUE(batch, InStream_Tell(instream) == gb6 + 10,
+    TEST_TRUE(runner, InStream_Tell(instream) == gb6 + 10,
               "Tell after seek forwards within buffer");
-    TEST_TRUE(batch, instream->buf == ((char*)NULL) + 10,
+    TEST_TRUE(runner, instream->buf == ((char*)NULL) + 10,
               "Seek within buffer sets buf");
-    TEST_TRUE(batch, instream->limit == ((char*)NULL) + gb1,
+    TEST_TRUE(runner, instream->limit == ((char*)NULL) + gb1,
               "Seek within buffer leaves limit alone");
 
     InStream_Seek(instream, gb6 + 1);
-    TEST_TRUE(batch, InStream_Tell(instream) == gb6 + 1,
+    TEST_TRUE(runner, InStream_Tell(instream) == gb6 + 1,
               "Tell after seek backwards within buffer");
-    TEST_TRUE(batch, instream->buf == ((char*)NULL) + 1,
+    TEST_TRUE(runner, instream->buf == ((char*)NULL) + 1,
               "Seek backwards within buffer sets buf");
-    TEST_TRUE(batch, instream->limit == ((char*)NULL) + gb1,
+    TEST_TRUE(runner, instream->limit == ((char*)NULL) + gb1,
               "Seek backwards within buffer leaves limit alone");
 
     InStream_Seek(instream, gb3);
-    TEST_TRUE(batch, InStream_Tell(instream) == gb3,
+    TEST_TRUE(runner, InStream_Tell(instream) == gb3,
               "Tell after seek backwards outside buffer");
-    TEST_TRUE(batch, instream->buf == NULL,
+    TEST_TRUE(runner, instream->buf == NULL,
               "Seek backwards outside buffer sets buf to NULL");
-    TEST_TRUE(batch, instream->limit == NULL,
+    TEST_TRUE(runner, instream->limit == NULL,
               "Seek backwards outside buffer sets limit to NULL");
-    TEST_TRUE(batch, instream->window->offset == gb3,
+    TEST_TRUE(runner, instream->window->offset == gb3,
               "Seek backwards outside buffer tracks pos in window offset");
 
     DECREF(instream);
@@ -214,12 +208,12 @@ test_Seek_and_Tell(TestBatch *batch) {
 }
 
 void
-TestInStream_run_tests(TestInStream *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_refill(batch);
-    test_Clone_and_Reopen(batch);
-    test_Close(batch);
-    test_Seek_and_Tell(batch);
+TestInStream_run(TestInStream *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 37);
+    test_refill(runner);
+    test_Clone_and_Reopen(runner);
+    test_Close(runner);
+    test_Seek_and_Tell(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestInStream.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestInStream.cfh b/core/Lucy/Test/Store/TestInStream.cfh
index 7b97094..b216fcd 100644
--- a/core/Lucy/Test/Store/TestInStream.cfh
+++ b/core/Lucy/Test/Store/TestInStream.cfh
@@ -24,13 +24,10 @@ class Lucy::Test::Store::TestInStream
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestInStream*
-    new(TestFormatter *formatter);
-
-    inert TestInStream*
-    init(TestInStream *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestInStream *self);
+    Run(TestInStream *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestRAMDirHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMDirHandle.c b/core/Lucy/Test/Store/TestRAMDirHandle.c
index 7997aa2..fd5cc00 100644
--- a/core/Lucy/Test/Store/TestRAMDirHandle.c
+++ b/core/Lucy/Test/Store/TestRAMDirHandle.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestRAMDirHandle.h"
 #include "Lucy/Store/FileHandle.h"
@@ -26,18 +26,12 @@
 #include "Lucy/Store/RAMDirHandle.h"
 
 TestRAMDirHandle*
-TestRAMDH_new(TestFormatter *formatter) {
-    TestRAMDirHandle *self = (TestRAMDirHandle*)VTable_Make_Obj(TESTRAMDIRHANDLE);
-    return TestRAMDH_init(self, formatter);
-}
-
-TestRAMDirHandle*
-TestRAMDH_init(TestRAMDirHandle *self, TestFormatter *formatter) {
-    return (TestRAMDirHandle*)TestBatch_init((TestBatch*)self, 6, formatter);
+TestRAMDH_new() {
+    return (TestRAMDirHandle*)VTable_Make_Obj(TESTRAMDIRHANDLE);
 }
 
 static void
-test_all(TestBatch *batch) {
+test_all(TestBatchRunner *runner) {
     RAMFolder *folder        = RAMFolder_new(NULL);
     CharBuf   *foo           = (CharBuf*)ZCB_WRAP_STR("foo", 3);
     CharBuf   *boffo         = (CharBuf*)ZCB_WRAP_STR("boffo", 5);
@@ -70,17 +64,17 @@ test_all(TestBatch *batch) {
             boffo_was_dir = RAMDH_Entry_Is_Dir(dh);
         }
     }
-    TEST_INT_EQ(batch, 2, count, "correct number of entries");
-    TEST_TRUE(batch, saw_foo, "Directory was iterated over");
-    TEST_TRUE(batch, foo_was_dir,
+    TEST_INT_EQ(runner, 2, count, "correct number of entries");
+    TEST_TRUE(runner, saw_foo, "Directory was iterated over");
+    TEST_TRUE(runner, foo_was_dir,
               "Dir correctly identified by Entry_Is_Dir");
-    TEST_TRUE(batch, saw_boffo, "File was iterated over");
-    TEST_FALSE(batch, boffo_was_dir,
+    TEST_TRUE(runner, saw_boffo, "File was iterated over");
+    TEST_FALSE(runner, boffo_was_dir,
                "File correctly identified by Entry_Is_Dir");
 
     uint32_t refcount = RAMFolder_Get_RefCount(folder);
     RAMDH_Close(dh);
-    TEST_INT_EQ(batch, RAMFolder_Get_RefCount(folder), refcount - 1,
+    TEST_INT_EQ(runner, RAMFolder_Get_RefCount(folder), refcount - 1,
                 "Folder reference released by Close()");
 
     DECREF(dh);
@@ -88,9 +82,9 @@ test_all(TestBatch *batch) {
 }
 
 void
-TestRAMDH_run_tests(TestRAMDirHandle *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_all(batch);
+TestRAMDH_run(TestRAMDirHandle *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
+    test_all(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestRAMDirHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMDirHandle.cfh b/core/Lucy/Test/Store/TestRAMDirHandle.cfh
index ac80e4d..31e242a 100644
--- a/core/Lucy/Test/Store/TestRAMDirHandle.cfh
+++ b/core/Lucy/Test/Store/TestRAMDirHandle.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestRAMDirHandle cnick TestRAMDH
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRAMDirHandle*
-    new(TestFormatter *formatter);
-
-    inert TestRAMDirHandle*
-    init(TestRAMDirHandle *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestRAMDirHandle *self);
+    Run(TestRAMDirHandle *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestRAMFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFileHandle.c b/core/Lucy/Test/Store/TestRAMFileHandle.c
index 0289c79..4a4bfb5 100644
--- a/core/Lucy/Test/Store/TestRAMFileHandle.c
+++ b/core/Lucy/Test/Store/TestRAMFileHandle.c
@@ -22,7 +22,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestRAMFileHandle.h"
 #include "Lucy/Store/RAMFileHandle.h"
@@ -30,30 +30,24 @@
 #include "Lucy/Store/RAMFile.h"
 
 TestRAMFileHandle*
-TestRAMFH_new(TestFormatter *formatter) {
-    TestRAMFileHandle *self = (TestRAMFileHandle*)VTable_Make_Obj(TESTRAMFILEHANDLE);
-    return TestRAMFH_init(self, formatter);
-}
-
-TestRAMFileHandle*
-TestRAMFH_init(TestRAMFileHandle *self, TestFormatter *formatter) {
-    return (TestRAMFileHandle*)TestBatch_init((TestBatch*)self, 32, formatter);
+TestRAMFH_new() {
+    return (TestRAMFileHandle*)VTable_Make_Obj(TESTRAMFILEHANDLE);
 }
 
 static void
-test_open(TestBatch *batch) {
+test_open(TestBatchRunner *runner) {
     RAMFileHandle *fh;
 
     Err_set_error(NULL);
     fh = RAMFH_open(NULL, FH_WRITE_ONLY, NULL);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "open() without a RAMFile or FH_CREATE returns NULL");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "open() without a RAMFile or FH_CREATE sets error");
 }
 
 static void
-test_Read_Write(TestBatch *batch) {
+test_Read_Write(TestBatchRunner *runner) {
     RAMFile *file = RAMFile_new(NULL, false);
     RAMFileHandle *fh = RAMFH_open(NULL, FH_WRITE_ONLY, file);
     const char *foo = "foo";
@@ -61,47 +55,47 @@ test_Read_Write(TestBatch *batch) {
     char buffer[12];
     char *buf = buffer;
 
-    TEST_TRUE(batch, CB_Equals_Str(RAMFH_Get_Path(fh), "", 0),
+    TEST_TRUE(runner, CB_Equals_Str(RAMFH_Get_Path(fh), "", 0),
               "NULL arg as filepath yields empty string");
 
-    TEST_TRUE(batch, RAMFH_Write(fh, foo, 3), "Write returns success");
-    TEST_TRUE(batch, RAMFH_Length(fh) == 3, "Length after one Write");
-    TEST_TRUE(batch, RAMFH_Write(fh, bar, 3), "Write returns success");
-    TEST_TRUE(batch, RAMFH_Length(fh) == 6, "Length after two Writes");
+    TEST_TRUE(runner, RAMFH_Write(fh, foo, 3), "Write returns success");
+    TEST_TRUE(runner, RAMFH_Length(fh) == 3, "Length after one Write");
+    TEST_TRUE(runner, RAMFH_Write(fh, bar, 3), "Write returns success");
+    TEST_TRUE(runner, RAMFH_Length(fh) == 6, "Length after two Writes");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, RAMFH_Read(fh, buf, 0, 2),
+    TEST_FALSE(runner, RAMFH_Read(fh, buf, 0, 2),
                "Reading from a write-only handle returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Reading from a write-only handle sets error");
 
     // Reopen for reading.
     DECREF(fh);
     fh = RAMFH_open(NULL, FH_READ_ONLY, file);
-    TEST_TRUE(batch, RAMFile_Read_Only(file),
+    TEST_TRUE(runner, RAMFile_Read_Only(file),
               "FH_READ_ONLY propagates to RAMFile's read_only property");
 
-    TEST_TRUE(batch, RAMFH_Read(fh, buf, 0, 6), "Read returns success");
-    TEST_TRUE(batch, strncmp(buf, "foobar", 6) == 0, "Read/Write");
-    TEST_TRUE(batch, RAMFH_Read(fh, buf, 2, 3), "Read returns success");
-    TEST_TRUE(batch, strncmp(buf, "oba", 3) == 0, "Read with offset");
+    TEST_TRUE(runner, RAMFH_Read(fh, buf, 0, 6), "Read returns success");
+    TEST_TRUE(runner, strncmp(buf, "foobar", 6) == 0, "Read/Write");
+    TEST_TRUE(runner, RAMFH_Read(fh, buf, 2, 3), "Read returns success");
+    TEST_TRUE(runner, strncmp(buf, "oba", 3) == 0, "Read with offset");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, RAMFH_Read(fh, buf, -1, 4),
+    TEST_FALSE(runner, RAMFH_Read(fh, buf, -1, 4),
                "Read() with a negative offset returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Read() with a negative offset sets error");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, RAMFH_Read(fh, buf, 6, 1),
+    TEST_FALSE(runner, RAMFH_Read(fh, buf, 6, 1),
                "Read() past EOF returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Read() past EOF sets error");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, RAMFH_Write(fh, foo, 3),
+    TEST_FALSE(runner, RAMFH_Write(fh, foo, 3),
                "Writing to a read-only handle returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Writing to a read-only handle sets error");
 
     DECREF(fh);
@@ -109,26 +103,26 @@ test_Read_Write(TestBatch *batch) {
 }
 
 static void
-test_Grow_and_Get_File(TestBatch *batch) {
+test_Grow_and_Get_File(TestBatchRunner *runner) {
     RAMFileHandle *fh = RAMFH_open(NULL, FH_WRITE_ONLY | FH_CREATE, NULL);
     RAMFile *ram_file = RAMFH_Get_File(fh);
     ByteBuf *contents = RAMFile_Get_Contents(ram_file);
 
     RAMFH_Grow(fh, 100);
-    TEST_TRUE(batch, BB_Get_Capacity(contents) >= 100, "Grow");
+    TEST_TRUE(runner, BB_Get_Capacity(contents) >= 100, "Grow");
 
     DECREF(fh);
 }
 
 static void
-test_Close(TestBatch *batch) {
+test_Close(TestBatchRunner *runner) {
     RAMFileHandle *fh = RAMFH_open(NULL, FH_WRITE_ONLY | FH_CREATE, NULL);
-    TEST_TRUE(batch, RAMFH_Close(fh), "Close returns true");
+    TEST_TRUE(runner, RAMFH_Close(fh), "Close returns true");
     DECREF(fh);
 }
 
 static void
-test_Window(TestBatch *batch) {
+test_Window(TestBatchRunner *runner) {
     RAMFile *file = RAMFile_new(NULL, false);
     RAMFileHandle *fh = RAMFH_open(NULL, FH_WRITE_ONLY, file);
     FileWindow *window = FileWindow_new();
@@ -143,26 +137,26 @@ test_Window(TestBatch *batch) {
     fh = RAMFH_open(NULL, FH_READ_ONLY, file);
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, RAMFH_Window(fh, window, -1, 4),
+    TEST_FALSE(runner, RAMFH_Window(fh, window, -1, 4),
                "Window() with a negative offset returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Window() with a negative offset sets error");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, RAMFH_Window(fh, window, 4000, 1000),
+    TEST_FALSE(runner, RAMFH_Window(fh, window, 4000, 1000),
                "Window() past EOF returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Window() past EOF sets error");
 
-    TEST_TRUE(batch, RAMFH_Window(fh, window, 1021, 2),
+    TEST_TRUE(runner, RAMFH_Window(fh, window, 1021, 2),
               "Window() returns true");
-    TEST_TRUE(batch, strncmp(window->buf, "oo", 2) == 0, "Window()");
+    TEST_TRUE(runner, strncmp(window->buf, "oo", 2) == 0, "Window()");
 
-    TEST_TRUE(batch, RAMFH_Release_Window(fh, window),
+    TEST_TRUE(runner, RAMFH_Release_Window(fh, window),
               "Release_Window() returns true");
-    TEST_TRUE(batch, window->buf == NULL, "Release_Window() resets buf");
-    TEST_TRUE(batch, window->offset == 0, "Release_Window() resets offset");
-    TEST_TRUE(batch, window->len == 0, "Release_Window() resets len");
+    TEST_TRUE(runner, window->buf == NULL, "Release_Window() resets buf");
+    TEST_TRUE(runner, window->offset == 0, "Release_Window() resets offset");
+    TEST_TRUE(runner, window->len == 0, "Release_Window() resets len");
 
     DECREF(window);
     DECREF(fh);
@@ -170,13 +164,13 @@ test_Window(TestBatch *batch) {
 }
 
 void
-TestRAMFH_run_tests(TestRAMFileHandle *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_open(batch);
-    test_Read_Write(batch);
-    test_Grow_and_Get_File(batch);
-    test_Close(batch);
-    test_Window(batch);
+TestRAMFH_run(TestRAMFileHandle *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 32);
+    test_open(runner);
+    test_Read_Write(runner);
+    test_Grow_and_Get_File(runner);
+    test_Close(runner);
+    test_Window(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestRAMFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFileHandle.cfh b/core/Lucy/Test/Store/TestRAMFileHandle.cfh
index 2b64af1..a795d23 100644
--- a/core/Lucy/Test/Store/TestRAMFileHandle.cfh
+++ b/core/Lucy/Test/Store/TestRAMFileHandle.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestRAMFileHandle cnick TestRAMFH
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRAMFileHandle*
-    new(TestFormatter *formatter);
-
-    inert TestRAMFileHandle*
-    init(TestRAMFileHandle *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestRAMFileHandle *self);
+    Run(TestRAMFileHandle *self, TestBatchRunner *runner);
 }
 
 


[lucy-commits] [02/26] git commit: refs/heads/separate-clownfish-wip2 - Rename more Lucy prefixes to Clownfish

Posted by nw...@apache.org.
Rename more Lucy prefixes to Clownfish


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/6cfc6291
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/6cfc6291
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/6cfc6291

Branch: refs/heads/separate-clownfish-wip2
Commit: 6cfc6291d3237ff5dfc2e37283c82507abca43b8
Parents: f1c9842
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun May 19 19:41:30 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:16 2013 +0200

----------------------------------------------------------------------
 c/src/Clownfish/Err.c                      |    2 +-
 c/t/test_lucy.c                            |    6 +-
 clownfish/compiler/src/CFCBindAliases.c    |  107 ++++++++++++++++++-
 core/Clownfish/CharBuf.c                   |    2 +-
 core/Clownfish/CharBuf.cfh                 |    6 +-
 core/Clownfish/Err.c                       |    4 +-
 core/Clownfish/Err.cfh                     |   57 +++++-----
 core/Clownfish/Hash.c                      |    4 +-
 core/Clownfish/LockFreeRegistry.c          |    8 +-
 core/Clownfish/Num.c                       |    2 +-
 core/Clownfish/Num.cfh                     |    4 +-
 core/Clownfish/Obj.cfh                     |   26 +++---
 core/Clownfish/Util/Atomic.c               |    4 +-
 core/Clownfish/Util/Atomic.cfh             |   26 +++---
 core/Clownfish/Util/Memory.cfh             |   16 ++--
 core/Clownfish/Util/NumberUtils.cfh        |   98 +++++++++---------
 core/Clownfish/Util/SortUtils.c            |   38 ++++----
 core/Clownfish/Util/SortUtils.cfh          |    8 +-
 core/Clownfish/Util/StringHelper.c         |    2 +-
 core/Clownfish/Util/StringHelper.cfh       |    4 +-
 core/Clownfish/VArray.c                    |    4 +-
 core/Clownfish/VArray.cfh                  |    8 +-
 core/Clownfish/VTable.c                    |    2 +-
 core/Lucy/Plan/FieldType.cfh               |    2 +-
 core/Lucy/Test.cfh                         |   16 ++--
 core/Lucy/Test/Index/TestTermInfo.c        |    2 +-
 core/Lucy/Util/Json.c                      |    6 +-
 core/Lucy/Util/Json.cfh                    |    4 +-
 core/Lucy/Util/SortExternal.c              |    8 +-
 perl/buildlib/Lucy/Build/Binding/Object.pm |    2 +-
 perl/buildlib/Lucy/Build/Binding/Util.pm   |    2 +-
 perl/xs/Lucy/Analysis/RegexTokenizer.c     |    2 +-
 perl/xs/Lucy/Document/Doc.c                |    2 +-
 perl/xs/XSBind.c                           |  132 +++++++++++-----------
 34 files changed, 358 insertions(+), 258 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/c/src/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/c/src/Clownfish/Err.c b/c/src/Clownfish/Err.c
index a233f74..2adb533 100644
--- a/c/src/Clownfish/Err.c
+++ b/c/src/Clownfish/Err.c
@@ -70,7 +70,7 @@ Err_to_host(Err *self) {
 void
 Err_throw_mess(VTable *vtable, CharBuf *message) {
     Err_Make_t make
-        = METHOD_PTR(CERTIFY(vtable, VTABLE), Lucy_Err_Make);
+        = METHOD_PTR(CERTIFY(vtable, VTABLE), Cfish_Err_Make);
     Err *err = (Err*)CERTIFY(make(NULL), ERR);
     Err_Cat_Mess(err, message);
     DECREF(message);

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/c/t/test_lucy.c
----------------------------------------------------------------------
diff --git a/c/t/test_lucy.c b/c/t/test_lucy.c
index f23847b..709b5d1 100644
--- a/c/t/test_lucy.c
+++ b/c/t/test_lucy.c
@@ -21,13 +21,13 @@
 
 int
 main() {
-    lucy_TestFormatterCF *formatter;
+    cfish_TestFormatterCF *formatter;
     bool success;
 
     lucy_bootstrap_parcel();
 
-    formatter = lucy_TestFormatterCF_new();
-    success = lucy_Test_run_all_batches((lucy_TestFormatter*)formatter);
+    formatter = cfish_TestFormatterCF_new();
+    success = lucy_Test_run_all_batches((cfish_TestFormatter*)formatter);
     CFISH_DECREF(formatter);
 
     return success ? EXIT_SUCCESS : EXIT_FAILURE;

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/clownfish/compiler/src/CFCBindAliases.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCBindAliases.c b/clownfish/compiler/src/CFCBindAliases.c
index 9eda959..0354080 100644
--- a/clownfish/compiler/src/CFCBindAliases.c
+++ b/clownfish/compiler/src/CFCBindAliases.c
@@ -28,10 +28,19 @@ struct alias aliases[] = {
 
     {"cfish_Obj", "lucy_Obj"},
     {"CFISH_OBJ", "LUCY_OBJ"},
+    {"cfish_Obj_dec_refcount", "lucy_Obj_dec_refcount"},
+    {"cfish_Obj_get_refcount", "lucy_Obj_get_refcount"},
+    {"cfish_Obj_inc_refcount", "lucy_Obj_inc_refcount"},
+    {"cfish_Obj_to_host", "lucy_Obj_to_host"},
+    {"Cfish_Obj_Destroy", "Lucy_Obj_Destroy"},
+    {"Cfish_Obj_Destroy_OFFSET", "Lucy_Obj_Destroy_OFFSET"},
+    {"Cfish_Obj_Destroy_t", "Lucy_Obj_Destroy_t"},
     {"Cfish_Obj_Dump", "Lucy_Obj_Dump"},
     {"Cfish_Obj_Get_Class_Name", "Lucy_Obj_Get_Class_Name"},
     {"Cfish_Obj_Is_A", "Lucy_Obj_Is_A"},
     {"Cfish_Obj_Load", "Lucy_Obj_Load"},
+    {"Cfish_Obj_Load_OFFSET", "Lucy_Obj_Load_OFFSET"},
+    {"Cfish_Obj_Load_t", "Lucy_Obj_Load_t"},
     {"Cfish_Obj_To_F64", "Lucy_Obj_To_F64"},
     {"Cfish_Obj_To_I64", "Lucy_Obj_To_I64"},
     {"Cfish_Obj_To_Bool", "Lucy_Obj_To_Bool"},
@@ -49,10 +58,14 @@ struct alias aliases[] = {
     {"cfish_CB_newf", "lucy_CB_newf"},
     {"cfish_CB_new_from_trusted_utf8", "lucy_CB_new_from_trusted_utf8"},
     {"Cfish_CB_Clone", "Lucy_CB_Clone"},
+    {"Cfish_CB_Nip_One_OFFSET", "Lucy_CB_Nip_One_OFFSET"},
+    {"Cfish_CB_Nip_One_t", "Lucy_CB_Nip_One_t"},
     {"cfish_ZombieCharBuf", "lucy_ZombieCharBuf"},
     {"CFISH_ZOMBIECHARBUF", "LUCY_ZOMBIECHARBUF"},
     {"CFISH_VIEWCHARBUF", "LUCY_VIEWCHARBUF"},
+    {"cfish_ZCB_new", "lucy_ZCB_new"},
     {"cfish_ZCB_size", "lucy_ZCB_size"},
+    {"cfish_ZCB_wrap", "lucy_ZCB_wrap"},
     {"cfish_ZCB_wrap_str", "lucy_ZCB_wrap_str"},
     {"Cfish_ZCB_Assign_Str", "Lucy_ZCB_Assign_Str"},
     {"Cfish_ZCB_Assign_Trusted_Str", "Lucy_ZCB_Assign_Trusted_Str"},
@@ -65,14 +78,36 @@ struct alias aliases[] = {
     {"CFISH_INTEGER64", "LUCY_INTEGER64"},
     {"CFISH_FLOAT32", "LUCY_FLOAT32"},
     {"CFISH_FLOAT64", "LUCY_FLOAT64"},
+    {"cfish_Bool_false_singleton", "lucy_Bool_false_singleton"},
+    {"cfish_Bool_true_singleton", "lucy_Bool_true_singleton"},
     {"cfish_Bool_singleton", "lucy_Bool_singleton"},
+    {"Cfish_Bool_Dec_RefCount_OFFSET", "Lucy_Bool_Dec_RefCount_OFFSET"},
+    {"Cfish_Bool_Dec_RefCount_t", "Lucy_Bool_Dec_RefCount_t"},
 
     {"cfish_Err", "lucy_Err"},
     {"CFISH_ERR", "LUCY_ERR"},
+    {"cfish_Err_certify", "lucy_Err_certify"},
+    {"cfish_Err_do_throw", "lucy_Err_do_throw"},
+    {"cfish_Err_downcast", "lucy_Err_downcast"},
+    {"cfish_Err_get_error", "lucy_Err_get_error"},
+    {"cfish_Err_init_class", "lucy_Err_init_class"},
+    {"cfish_Err_make_mess", "lucy_Err_make_mess"},
     {"cfish_Err_new", "lucy_Err_new"},
-    {"cfish_Err_trap", "lucy_Err_trap"},
+    {"cfish_Err_rethrow", "lucy_Err_rethrow"},
     {"cfish_Err_set_error", "lucy_Err_set_error"},
-    {"cfish_Err_get_error", "lucy_Err_get_error"},
+    {"cfish_Err_throw_at", "lucy_Err_throw_at"},
+    {"cfish_Err_throw_mess", "lucy_Err_throw_mess"},
+    {"cfish_Err_to_host", "lucy_Err_to_host"},
+    {"cfish_Err_trap", "lucy_Err_trap"},
+    {"cfish_Err_warn_at", "lucy_Err_warn_at"},
+    {"cfish_Err_warn_mess", "lucy_Err_warn_mess"},
+    {"Cfish_Err_Add_Frame", "Lucy_Err_Add_Frame"},
+    {"Cfish_Err_Cat_Mess", "Lucy_Err_Cat_Mess"},
+    {"Cfish_Err_Make_OFFSET", "Lucy_Err_Make_OFFSET"},
+    {"Cfish_Err_Make_t", "Lucy_Err_Make_t"},
+    {"Cfish_Err_To_Host", "Lucy_Err_To_Host"},
+    {"Cfish_Err_To_Host_OFFSET", "Lucy_Err_To_Host_OFFSET"},
+    {"Cfish_Err_To_Host_t", "Lucy_Err_To_Host_t"},
 
     {"cfish_Hash", "lucy_Hash"},
     {"CFISH_HASH", "LUCY_HASH"},
@@ -83,6 +118,62 @@ struct alias aliases[] = {
     {"Cfish_Hash_Store_Str", "Lucy_Hash_Store_Str"},
     {"Cfish_Hash_Store", "Lucy_Hash_Store"},
 
+    {"cfish_LockFreeRegistry", "lucy_LockFreeRegistry"},
+    {"CFISH_LOCKFREEREGISTRY", "LUCY_LOCKFREEREGISTRY"},
+    {"cfish_LFReg_to_host", "lucy_LFReg_to_host"},
+    {"Cfish_LFReg_To_Host", "Lucy_LFReg_To_Host"},
+    {"Cfish_LFReg_To_Host_OFFSET", "Lucy_LFReg_To_Host_OFFSET"},
+    {"Cfish_LFReg_To_Host_t", "Lucy_LFReg_To_Host_t"},
+
+    {"cfish_Memory_wrapped_calloc", "lucy_Memory_wrapped_calloc"},
+    {"cfish_Memory_wrapped_free", "lucy_Memory_wrapped_free"},
+    {"cfish_Memory_wrapped_malloc", "lucy_Memory_wrapped_malloc"},
+    {"cfish_Memory_wrapped_realloc", "lucy_Memory_wrapped_realloc"},
+
+    {"cfish_NumUtil_decode_bigend_f32", "lucy_NumUtil_decode_bigend_f32"},
+    {"cfish_NumUtil_decode_bigend_f64", "lucy_NumUtil_decode_bigend_f64"},
+    {"cfish_NumUtil_decode_bigend_u16", "lucy_NumUtil_decode_bigend_u16"},
+    {"cfish_NumUtil_decode_bigend_u32", "lucy_NumUtil_decode_bigend_u32"},
+    {"cfish_NumUtil_decode_bigend_u64", "lucy_NumUtil_decode_bigend_u64"},
+    {"cfish_NumUtil_decode_c32", "lucy_NumUtil_decode_c32"},
+    {"cfish_NumUtil_decode_c64", "lucy_NumUtil_decode_c64"},
+    {"cfish_NumUtil_encode_bigend_f32", "lucy_NumUtil_encode_bigend_f32"},
+    {"cfish_NumUtil_encode_bigend_f64", "lucy_NumUtil_encode_bigend_f64"},
+    {"cfish_NumUtil_encode_bigend_u16", "lucy_NumUtil_encode_bigend_u16"},
+    {"cfish_NumUtil_encode_bigend_u32", "lucy_NumUtil_encode_bigend_u32"},
+    {"cfish_NumUtil_encode_bigend_u64", "lucy_NumUtil_encode_bigend_u64"},
+    {"cfish_NumUtil_encode_c32", "lucy_NumUtil_encode_c32"},
+    {"cfish_NumUtil_encode_c64", "lucy_NumUtil_encode_c64"},
+    {"cfish_NumUtil_encode_padded_c32", "lucy_NumUtil_encode_padded_c32"},
+    {"cfish_NumUtil_u1clear", "lucy_NumUtil_u1clear"},
+    {"cfish_NumUtil_u1flip", "lucy_NumUtil_u1flip"},
+    {"cfish_NumUtil_u1get", "lucy_NumUtil_u1get"},
+    {"cfish_NumUtil_u1set", "lucy_NumUtil_u1set"},
+    {"cfish_NumUtil_u1masks", "lucy_NumUtil_u1masks"},
+    {"cfish_NumUtil_u2get", "lucy_NumUtil_u2get"},
+    {"cfish_NumUtil_u2set", "lucy_NumUtil_u2set"},
+    {"cfish_NumUtil_u2masks", "lucy_NumUtil_u2masks"},
+    {"cfish_NumUtil_u2shifts", "lucy_NumUtil_u2shifts"},
+    {"cfish_NumUtil_u4get", "lucy_NumUtil_u4get"},
+    {"cfish_NumUtil_u4set", "lucy_NumUtil_u4set"},
+    {"cfish_NumUtil_u4masks", "lucy_NumUtil_u4masks"},
+    {"cfish_NumUtil_u4shifts", "lucy_NumUtil_u4shifts"},
+    {"cfish_NumUtil_skip_cint", "lucy_NumUtil_skip_cint"},
+
+    {"cfish_StrHelp_UTF8_COUNT", "lucy_StrHelp_UTF8_COUNT"},
+
+    {"cfish_TestBatch_fail", "lucy_TestBatch_fail"},
+    {"cfish_TestBatch_pass", "lucy_TestBatch_pass"},
+    {"cfish_TestBatch_skip", "lucy_TestBatch_skip"},
+    {"cfish_TestBatch_test_false", "lucy_TestBatch_test_false"},
+    {"cfish_TestBatch_test_float_equals", "lucy_TestBatch_test_float_equals"},
+    {"cfish_TestBatch_test_int_equals", "lucy_TestBatch_test_int_equals"},
+    {"cfish_TestBatch_test_string_equals", "lucy_TestBatch_test_string_equals"},
+    {"cfish_TestBatch_test_true", "lucy_TestBatch_test_true"},
+    {"cfish_TestFormatter", "lucy_TestFormatter"},
+    {"cfish_TestFormatterCF", "lucy_TestFormatterCF"},
+    {"cfish_TestFormatterCF_new", "lucy_TestFormatterCF_new"},
+
     {"cfish_VArray", "lucy_VArray"},
     {"CFISH_VARRAY", "LUCY_VARRAY"},
     {"cfish_VA_new", "lucy_VA_new"},
@@ -94,12 +185,22 @@ struct alias aliases[] = {
 
     {"cfish_VTable", "lucy_VTable"},
     {"CFISH_VTABLE", "LUCY_VTABLE"},
-    {"cfish_VTable_bootstrap", "lucy_VTable_bootstrap"},
     {"cfish_VTable_add_alias_to_registry", "lucy_VTable_add_alias_to_registry"},
+    {"cfish_VTable_bootstrap", "lucy_VTable_bootstrap"},
+    {"cfish_VTable_find_parent_class", "lucy_VTable_find_parent_class"},
+    {"cfish_VTable_foster_obj", "lucy_VTable_foster_obj"},
+    {"cfish_VTable_fresh_host_methods", "lucy_VTable_fresh_host_methods"},
+    {"cfish_VTable_init_obj", "lucy_VTable_init_obj"},
+    {"cfish_VTable_make_obj", "lucy_VTable_make_obj"},
     {"cfish_VTable_offset_of_parent", "lucy_VTable_offset_of_parent"},
+    {"cfish_VTable_register_with_host", "lucy_VTable_register_with_host"},
     {"cfish_VTable_singleton", "lucy_VTable_singleton"},
+    {"cfish_VTable_to_host", "lucy_VTable_to_host"},
     {"Cfish_VTable_Get_Name", "Lucy_VTable_Get_Name"},
     {"Cfish_VTable_Make_Obj", "Lucy_VTable_Make_Obj"},
+    {"Cfish_VTable_To_Host", "Lucy_VTable_To_Host"},
+    {"Cfish_VTable_To_Host_OFFSET", "Lucy_VTable_To_Host_OFFSET"},
+    {"Cfish_VTable_To_Host_t", "Lucy_VTable_To_Host_t"},
 
     {"CFISH_USE_SHORT_NAMES", "LUCY_USE_SHORT_NAMES"},
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/CharBuf.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/CharBuf.c b/core/Clownfish/CharBuf.c
index 88474eb..fda1646 100644
--- a/core/Clownfish/CharBuf.c
+++ b/core/Clownfish/CharBuf.c
@@ -133,7 +133,7 @@ CB_hash_sum(CharBuf *self) {
     uint32_t hashvalue = 5381;
     ZombieCharBuf *iterator = ZCB_WRAP(self);
 
-    const CB_Nip_One_t nip_one = METHOD_PTR(iterator->vtable, Lucy_CB_Nip_One);
+    const CB_Nip_One_t nip_one = METHOD_PTR(iterator->vtable, Cfish_CB_Nip_One);
     while (iterator->size) {
         uint32_t code_point = (uint32_t)nip_one((CharBuf*)iterator);
         hashvalue = ((hashvalue << 5) + hashvalue) ^ code_point;

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/CharBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/CharBuf.cfh b/core/Clownfish/CharBuf.cfh
index f9d9ab5..6eeca16 100644
--- a/core/Clownfish/CharBuf.cfh
+++ b/core/Clownfish/CharBuf.cfh
@@ -387,13 +387,13 @@ class Clownfish::ZombieCharBuf cnick ZCB
 
 __C__
 
-#define CFISH_ZCB_BLANK() lucy_ZCB_new(alloca(lucy_ZCB_size()))
+#define CFISH_ZCB_BLANK() cfish_ZCB_new(alloca(cfish_ZCB_size()))
 
 #define CFISH_ZCB_WRAP(source) \
-    lucy_ZCB_wrap(alloca(lucy_ZCB_size()), source)
+    cfish_ZCB_wrap(alloca(cfish_ZCB_size()), source)
 
 #define CFISH_ZCB_WRAP_STR(ptr, size) \
-    lucy_ZCB_wrap_str(alloca(lucy_ZCB_size()), ptr, size)
+    cfish_ZCB_wrap_str(alloca(cfish_ZCB_size()), ptr, size)
 
 #ifdef LUCY_USE_SHORT_NAMES
   #define ZCB_BLANK             CFISH_ZCB_BLANK

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Err.c b/core/Clownfish/Err.c
index ee9f930..0a6e979 100644
--- a/core/Clownfish/Err.c
+++ b/core/Clownfish/Err.c
@@ -68,7 +68,7 @@ Err_cat_mess(Err *self, const CharBuf *mess) {
 void
 THROW(VTable *vtable, char *pattern, ...) {
     va_list args;
-    Err_Make_t make = METHOD_PTR(CERTIFY(vtable, VTABLE), Lucy_Err_Make);
+    Err_Make_t make = METHOD_PTR(CERTIFY(vtable, VTABLE), Cfish_Err_Make);
     Err *err = (Err*)CERTIFY(make(NULL), ERR);
     CharBuf *mess = Err_Get_Mess(err);
 
@@ -171,7 +171,7 @@ void
 Err_throw_at(VTable *vtable, const char *file, int line,
              const char *func, const char *pattern, ...) {
     va_list args;
-    Err_Make_t make = METHOD_PTR(CERTIFY(vtable, VTABLE), Lucy_Err_Make);
+    Err_Make_t make = METHOD_PTR(CERTIFY(vtable, VTABLE), Cfish_Err_Make);
     Err *err = (Err*)CERTIFY(make(NULL), ERR);
     CharBuf *mess = Err_Get_Mess(err);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Err.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Err.cfh b/core/Clownfish/Err.cfh
index 777aab2..80ca136 100644
--- a/core/Clownfish/Err.cfh
+++ b/core/Clownfish/Err.cfh
@@ -18,9 +18,8 @@ parcel Lucy;
 
 __C__
 typedef void 
-(*Lucy_Err_Attempt_t)(void *context);
+(*Cfish_Err_Attempt_t)(void *context);
 
-#define Cfish_Err_Attempt_t Lucy_Err_Attempt_t
 #ifdef LUCY_USE_SHORT_NAMES
   #define Err_Attempt_t Cfish_Err_Attempt_t
 #endif
@@ -181,66 +180,66 @@ __C__
 #endif
 
 #define CFISH_ERR_ADD_FRAME(_error) \
-    Lucy_Err_Add_Frame(_error, __FILE__, __LINE__, \
-                       CFISH_ERR_FUNC_MACRO)
+    Cfish_Err_Add_Frame(_error, __FILE__, __LINE__, \
+                        CFISH_ERR_FUNC_MACRO)
 
 #define CFISH_RETHROW(_error) \
-    lucy_Err_rethrow((lucy_Err*)_error, __FILE__, __LINE__, \
-                     CFISH_ERR_FUNC_MACRO)
+    cfish_Err_rethrow((cfish_Err*)_error, __FILE__, __LINE__, \
+                      CFISH_ERR_FUNC_MACRO)
 
-/** Macro version of lucy_Err_throw_at which inserts contextual information
+/** Macro version of cfish_Err_throw_at which inserts contextual information
  * automatically, provided that the compiler supports the necessary features.
  */
 #ifdef CHY_HAS_VARIADIC_MACROS
  #ifdef CHY_HAS_ISO_VARIADIC_MACROS
   #define CFISH_THROW(_vtable, ...) \
-    lucy_Err_throw_at(_vtable, __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, \
-                      __VA_ARGS__)
+    cfish_Err_throw_at(_vtable, __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, \
+                       __VA_ARGS__)
   #define CFISH_WARN(...) \
-    lucy_Err_warn_at(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, __VA_ARGS__)
+    cfish_Err_warn_at(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, __VA_ARGS__)
   #define CFISH_MAKE_MESS(...) \
-    lucy_Err_make_mess(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, \
-                       __VA_ARGS__)
+    cfish_Err_make_mess(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, \
+                        __VA_ARGS__)
  #elif defined(CHY_HAS_GNUC_VARIADIC_MACROS)
   #define CFISH_THROW(_vtable, args...) \
-    lucy_Err_throw_at(_vtable, __FILE__, __LINE__, \
-                      CFISH_ERR_FUNC_MACRO, ##args)
+    cfish_Err_throw_at(_vtable, __FILE__, __LINE__, \
+                       CFISH_ERR_FUNC_MACRO, ##args)
   #define CFISH_WARN(args...) \
-    lucy_Err_warn_at(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, ##args)
+    cfish_Err_warn_at(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, ##args)
   #define CFISH_MAKE_MESS(args...) \
-    lucy_Err_make_mess(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, ##args)
+    cfish_Err_make_mess(__FILE__, __LINE__, CFISH_ERR_FUNC_MACRO, ##args)
  #endif
 #else
   void
-  CFISH_THROW(lucy_VTable *vtable, char* format, ...);
+  CFISH_THROW(cfish_VTable *vtable, char* format, ...);
   void
   CFISH_WARN(char* format, ...);
-  lucy_CharBuf*
+  cfish_CharBuf*
   CFISH_MAKE_MESS(char* format, ...);
 #endif
 
 #define CFISH_DOWNCAST(_obj, _vtable) \
-    lucy_Err_downcast((lucy_Obj*)(_obj), (_vtable), \
-                      __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)
+    cfish_Err_downcast((cfish_Obj*)(_obj), (_vtable), \
+                       __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)
 
 
 #define CFISH_CERTIFY(_obj, _vtable) \
-    lucy_Err_certify((lucy_Obj*)(_obj), (_vtable), \
-                     __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)
+    cfish_Err_certify((cfish_Obj*)(_obj), (_vtable), \
+                      __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)
 
 static CFISH_INLINE void
-lucy_Err_abstract_class_check(lucy_Obj *obj, lucy_VTable *vtable) {
-    lucy_VTable *const my_vtable = (lucy_VTable*)((cfish_Dummy*)obj)->vtable;
+cfish_Err_abstract_class_check(cfish_Obj *obj, cfish_VTable *vtable) {
+    cfish_VTable *const my_vtable = (cfish_VTable*)((cfish_Dummy*)obj)->vtable;
     if (my_vtable == vtable) {
-        lucy_CharBuf *mess = CFISH_MAKE_MESS("%o is an abstract class",
-                                             Lucy_Obj_Get_Class_Name(obj));
-        Lucy_Obj_Dec_RefCount(obj);
-        lucy_Err_throw_mess(LUCY_ERR, mess);
+        cfish_CharBuf *mess = CFISH_MAKE_MESS("%o is an abstract class",
+                                              Cfish_Obj_Get_Class_Name(obj));
+        Cfish_Obj_Dec_RefCount(obj);
+        cfish_Err_throw_mess(CFISH_ERR, mess);
     }
 }
 
 #define CFISH_ABSTRACT_CLASS_CHECK(_obj, _vtable) \
-    lucy_Err_abstract_class_check(((lucy_Obj*)_obj), _vtable)
+    cfish_Err_abstract_class_check(((cfish_Obj*)_obj), _vtable)
 
 #ifdef LUCY_USE_SHORT_NAMES
   #define THROW                 CFISH_THROW

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Hash.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Hash.c b/core/Clownfish/Hash.c
index 40c9a0b..59c4854 100644
--- a/core/Clownfish/Hash.c
+++ b/core/Clownfish/Hash.c
@@ -35,7 +35,7 @@
 
 static HashTombStone *TOMBSTONE;
 
-#define HashEntry lucy_HashEntry
+#define HashEntry cfish_HashEntry
 
 typedef struct HashEntry {
     Obj     *key;
@@ -144,7 +144,7 @@ Hash_load(Hash *self, Obj *dump) {
 
         // Dispatch to an alternate Load() method.
         if (vtable) {
-            Obj_Load_t load = METHOD_PTR(vtable, Lucy_Obj_Load);
+            Obj_Load_t load = METHOD_PTR(vtable, Cfish_Obj_Load);
             if (load == Obj_load) {
                 THROW(ERR, "Abstract method Load() not defined for %o",
                       VTable_Get_Name(vtable));

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/LockFreeRegistry.c b/core/Clownfish/LockFreeRegistry.c
index 519dc51..11ab071 100644
--- a/core/Clownfish/LockFreeRegistry.c
+++ b/core/Clownfish/LockFreeRegistry.c
@@ -24,13 +24,13 @@
 #include "Clownfish/Util/Atomic.h"
 #include "Clownfish/Util/Memory.h"
 
-typedef struct lucy_LFRegEntry {
+typedef struct cfish_LFRegEntry {
     Obj *key;
     Obj *value;
     int32_t hash_sum;
-    struct lucy_LFRegEntry *volatile next;
-} lucy_LFRegEntry;
-#define LFRegEntry lucy_LFRegEntry
+    struct cfish_LFRegEntry *volatile next;
+} cfish_LFRegEntry;
+#define LFRegEntry cfish_LFRegEntry
 
 LockFreeRegistry*
 LFReg_new(size_t capacity) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Num.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Num.c b/core/Clownfish/Num.c
index 8d49ab1..e40f825 100644
--- a/core/Clownfish/Num.c
+++ b/core/Clownfish/Num.c
@@ -438,7 +438,7 @@ Bool_deserialize(BoolNum *self, InStream *instream) {
     bool value = (bool)InStream_Read_U8(instream);
     if (self && self != CFISH_TRUE && self != CFISH_FALSE) {
         Bool_Dec_RefCount_t super_decref
-            = SUPER_METHOD_PTR(BOOLNUM, Lucy_Bool_Dec_RefCount);
+            = SUPER_METHOD_PTR(BOOLNUM, Cfish_Bool_Dec_RefCount);
         super_decref(self);
     }
     return value ? CFISH_TRUE : CFISH_FALSE;

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Num.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Num.cfh b/core/Clownfish/Num.cfh
index 0ff37be..a684fe1 100644
--- a/core/Clownfish/Num.cfh
+++ b/core/Clownfish/Num.cfh
@@ -300,8 +300,8 @@ class Clownfish::BoolNum cnick Bool inherits Clownfish::IntNum {
 
 __C__
 
-#define CFISH_TRUE  lucy_Bool_true_singleton
-#define CFISH_FALSE lucy_Bool_false_singleton
+#define CFISH_TRUE  cfish_Bool_true_singleton
+#define CFISH_FALSE cfish_Bool_false_singleton
 
 __END_C__
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Obj.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Obj.cfh b/core/Clownfish/Obj.cfh
index a801b48..a7370fb 100644
--- a/core/Clownfish/Obj.cfh
+++ b/core/Clownfish/Obj.cfh
@@ -188,33 +188,33 @@ public class Clownfish::Obj {
 
 __C__
 static CFISH_INLINE void
-lucy_Obj_super_destroy(lucy_Obj *self, lucy_VTable *vtable) {
-    Lucy_Obj_Destroy_t super_destroy
-        = CFISH_SUPER_METHOD_PTR(vtable, Lucy_Obj_Destroy);
+cfish_Obj_super_destroy(cfish_Obj *self, cfish_VTable *vtable) {
+    Cfish_Obj_Destroy_t super_destroy
+        = CFISH_SUPER_METHOD_PTR(vtable, Cfish_Obj_Destroy);
     super_destroy(self);
 }
 
-#define LUCY_SUPER_DESTROY(_self, _vtable) \
-    lucy_Obj_super_destroy((lucy_Obj*)_self, _vtable)
+#define CFISH_SUPER_DESTROY(_self, _vtable) \
+    cfish_Obj_super_destroy((cfish_Obj*)_self, _vtable)
 
-static CFISH_INLINE lucy_Obj*
-lucy_Obj_incref(lucy_Obj *self) {
-    if (self != NULL) { return Lucy_Obj_Inc_RefCount(self); }
+static CFISH_INLINE cfish_Obj*
+cfish_Obj_incref(cfish_Obj *self) {
+    if (self != NULL) { return Cfish_Obj_Inc_RefCount(self); }
     else { return NULL; }
 }
 
-#define CFISH_INCREF(_self) lucy_Obj_incref((lucy_Obj*)_self)
+#define CFISH_INCREF(_self) cfish_Obj_incref((cfish_Obj*)_self)
 
 static CFISH_INLINE uint32_t
-lucy_Obj_decref(lucy_Obj *self) {
-    if (self != NULL) { return Lucy_Obj_Dec_RefCount(self); }
+cfish_Obj_decref(cfish_Obj *self) {
+    if (self != NULL) { return Cfish_Obj_Dec_RefCount(self); }
     else { return 0; }
 }
 
-#define CFISH_DECREF(_self) lucy_Obj_decref((lucy_Obj*)_self)
+#define CFISH_DECREF(_self) cfish_Obj_decref((cfish_Obj*)_self)
 
 #ifdef LUCY_USE_SHORT_NAMES
-  #define SUPER_DESTROY(_self, _vtable)   LUCY_SUPER_DESTROY(_self, _vtable)
+  #define SUPER_DESTROY(_self, _vtable)   CFISH_SUPER_DESTROY(_self, _vtable)
   #define INCREF(_self)                   CFISH_INCREF(_self)
   #define DECREF(_self)                   CFISH_DECREF(_self)
 #endif

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Util/Atomic.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/Atomic.c b/core/Clownfish/Util/Atomic.c
index 62c43e2..8bf776a 100644
--- a/core/Clownfish/Util/Atomic.c
+++ b/core/Clownfish/Util/Atomic.c
@@ -23,7 +23,7 @@
 #include <windows.h>
 
 bool
-lucy_Atomic_wrapped_cas_ptr(void *volatile *target, void *old_value,
+cfish_Atomic_wrapped_cas_ptr(void *volatile *target, void *old_value,
                             void *new_value) {
     return InterlockedCompareExchangePointer(target, new_value, old_value)
            == old_value;
@@ -33,7 +33,7 @@ lucy_Atomic_wrapped_cas_ptr(void *volatile *target, void *old_value,
 #elif defined(CHY_HAS_PTHREAD_H)
 
 #include <pthread.h>
-pthread_mutex_t lucy_Atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t cfish_Atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 #endif
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Util/Atomic.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/Atomic.cfh b/core/Clownfish/Util/Atomic.cfh
index 91d3d6b..da741ce 100644
--- a/core/Clownfish/Util/Atomic.cfh
+++ b/core/Clownfish/Util/Atomic.cfh
@@ -27,13 +27,13 @@ __C__
  * <code>new_value</code> and return true.  Otherwise, return false.
  */
 static CFISH_INLINE bool
-lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value);
+cfish_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value);
 
 /************************** Single threaded *******************************/
 #ifdef LUCY_NOTHREADS
 
 static CFISH_INLINE bool
-lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
+cfish_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
     if (*target == old_value) {
         *target = new_value;
         return true;
@@ -48,7 +48,7 @@ lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
 #include <libkern/OSAtomic.h>
 
 static CFISH_INLINE bool
-lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
+cfish_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
     return OSAtomicCompareAndSwapPtr(old_value, new_value, target);
 }
 
@@ -56,12 +56,12 @@ lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
 #elif defined(CHY_HAS_WINDOWS_H)
 
 bool
-lucy_Atomic_wrapped_cas_ptr(void *volatile *target, void *old_value,
+cfish_Atomic_wrapped_cas_ptr(void *volatile *target, void *old_value,
                             void *new_value);
 
 static CFISH_INLINE bool
-lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
-    return lucy_Atomic_wrapped_cas_ptr(target, old_value, new_value);
+cfish_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
+    return cfish_Atomic_wrapped_cas_ptr(target, old_value, new_value);
 }
 
 /**************************** Solaris 10 and later ************************/
@@ -69,7 +69,7 @@ lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
 #include <sys/atomic.h>
 
 static CFISH_INLINE bool
-lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
+cfish_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
     return atomic_cas_ptr(target, old_value, new_value) == old_value;
 }
 
@@ -77,18 +77,18 @@ lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
 #elif defined(CHY_HAS_PTHREAD_H)
 #include <pthread.h>
 
-extern pthread_mutex_t lucy_Atomic_mutex;
+extern pthread_mutex_t cfish_Atomic_mutex;
 
 static CFISH_INLINE bool
-lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
-    pthread_mutex_lock(&lucy_Atomic_mutex);
+cfish_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
+    pthread_mutex_lock(&cfish_Atomic_mutex);
     if (*target == old_value) {
         *target = new_value;
-        pthread_mutex_unlock(&lucy_Atomic_mutex);
+        pthread_mutex_unlock(&cfish_Atomic_mutex);
         return true;
     }
     else {
-        pthread_mutex_unlock(&lucy_Atomic_mutex);
+        pthread_mutex_unlock(&cfish_Atomic_mutex);
         return false;
     }
 }
@@ -101,7 +101,7 @@ lucy_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
 #endif // Big platform if-else chain.
 
 #ifdef LUCY_USE_SHORT_NAMES
-  #define Atomic_cas_ptr lucy_Atomic_cas_ptr
+  #define Atomic_cas_ptr cfish_Atomic_cas_ptr
 #endif
 
 __END_C__

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Util/Memory.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/Memory.cfh b/core/Clownfish/Util/Memory.cfh
index cd249b4..e5ed310 100644
--- a/core/Clownfish/Util/Memory.cfh
+++ b/core/Clownfish/Util/Memory.cfh
@@ -56,16 +56,16 @@ inert class Clownfish::Util::Memory {
 
 __C__
 
-#define LUCY_MALLOCATE    lucy_Memory_wrapped_malloc
-#define LUCY_CALLOCATE    lucy_Memory_wrapped_calloc
-#define LUCY_REALLOCATE   lucy_Memory_wrapped_realloc
-#define LUCY_FREEMEM      lucy_Memory_wrapped_free
+#define CFISH_MALLOCATE    cfish_Memory_wrapped_malloc
+#define CFISH_CALLOCATE    cfish_Memory_wrapped_calloc
+#define CFISH_REALLOCATE   cfish_Memory_wrapped_realloc
+#define CFISH_FREEMEM      cfish_Memory_wrapped_free
 
 #ifdef LUCY_USE_SHORT_NAMES
-  #define MALLOCATE                       LUCY_MALLOCATE
-  #define CALLOCATE                       LUCY_CALLOCATE
-  #define REALLOCATE                      LUCY_REALLOCATE
-  #define FREEMEM                         LUCY_FREEMEM
+  #define MALLOCATE                       CFISH_MALLOCATE
+  #define CALLOCATE                       CFISH_CALLOCATE
+  #define REALLOCATE                      CFISH_REALLOCATE
+  #define FREEMEM                         CFISH_FREEMEM
 #endif
 
 __END_C__

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Util/NumberUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/NumberUtils.cfh b/core/Clownfish/Util/NumberUtils.cfh
index 11a5afd..e94b90c 100644
--- a/core/Clownfish/Util/NumberUtils.cfh
+++ b/core/Clownfish/Util/NumberUtils.cfh
@@ -181,7 +181,7 @@ __C__
 #include <string.h>
 
 static CFISH_INLINE void
-lucy_NumUtil_encode_bigend_u16(uint16_t value, void *dest_ptr) {
+cfish_NumUtil_encode_bigend_u16(uint16_t value, void *dest_ptr) {
     uint8_t *dest = *(uint8_t**)dest_ptr;
 #ifdef CHY_BIG_END
     memcpy(dest, &value, sizeof(uint16_t));
@@ -193,7 +193,7 @@ lucy_NumUtil_encode_bigend_u16(uint16_t value, void *dest_ptr) {
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_encode_bigend_u32(uint32_t value, void *dest_ptr) {
+cfish_NumUtil_encode_bigend_u32(uint32_t value, void *dest_ptr) {
     uint8_t *dest = *(uint8_t**)dest_ptr;
 #ifdef CHY_BIG_END
     memcpy(dest, &value, sizeof(uint32_t));
@@ -207,7 +207,7 @@ lucy_NumUtil_encode_bigend_u32(uint32_t value, void *dest_ptr) {
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_encode_bigend_u64(uint64_t value, void *dest_ptr) {
+cfish_NumUtil_encode_bigend_u64(uint64_t value, void *dest_ptr) {
     uint8_t *dest = *(uint8_t**)dest_ptr;
 #ifdef CHY_BIG_END
     memcpy(dest, &value, sizeof(uint64_t));
@@ -225,14 +225,14 @@ lucy_NumUtil_encode_bigend_u64(uint64_t value, void *dest_ptr) {
 }
 
 static CFISH_INLINE uint16_t
-lucy_NumUtil_decode_bigend_u16(void *source) {
+cfish_NumUtil_decode_bigend_u16(void *source) {
     uint8_t *const buf = (uint8_t*)source;
     return  (buf[0] << 8) |
             (buf[1]);
 }
 
 static CFISH_INLINE uint32_t
-lucy_NumUtil_decode_bigend_u32(void *source) {
+cfish_NumUtil_decode_bigend_u32(void *source) {
     uint8_t *const buf = (uint8_t*)source;
     return  (buf[0]  << 24) |
             (buf[1]  << 16) |
@@ -241,7 +241,7 @@ lucy_NumUtil_decode_bigend_u32(void *source) {
 }
 
 static CFISH_INLINE uint64_t
-lucy_NumUtil_decode_bigend_u64(void *source) {
+cfish_NumUtil_decode_bigend_u64(void *source) {
     uint8_t *const buf = (uint8_t*)source;
     uint64_t high_bits = (buf[0]  << 24) |
                          (buf[1]  << 16) |
@@ -257,55 +257,55 @@ lucy_NumUtil_decode_bigend_u64(void *source) {
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_encode_bigend_f32(float value, void *dest_ptr) {
+cfish_NumUtil_encode_bigend_f32(float value, void *dest_ptr) {
     uint8_t *dest = *(uint8_t**)dest_ptr;
 #ifdef CHY_BIG_END
     memcpy(dest, &value, sizeof(float));
 #else
     union { float f; uint32_t u32; } duo;
     duo.f = value;
-    lucy_NumUtil_encode_bigend_u32(duo.u32, &dest);
+    cfish_NumUtil_encode_bigend_u32(duo.u32, &dest);
 #endif
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_encode_bigend_f64(double value, void *dest_ptr) {
+cfish_NumUtil_encode_bigend_f64(double value, void *dest_ptr) {
     uint8_t *dest = *(uint8_t**)dest_ptr;
 #ifdef CHY_BIG_END
     memcpy(dest, &value, sizeof(double));
 #else
     union { double d; uint64_t u64; } duo;
     duo.d = value;
-    lucy_NumUtil_encode_bigend_u64(duo.u64, &dest);
+    cfish_NumUtil_encode_bigend_u64(duo.u64, &dest);
 #endif
 }
 
 static CFISH_INLINE float
-lucy_NumUtil_decode_bigend_f32(void *source) {
+cfish_NumUtil_decode_bigend_f32(void *source) {
     union { float f; uint32_t u32; } duo;
     memcpy(&duo, source, sizeof(float));
 #ifdef CHY_LITTLE_END
-    duo.u32 = lucy_NumUtil_decode_bigend_u32(&duo.u32);
+    duo.u32 = cfish_NumUtil_decode_bigend_u32(&duo.u32);
 #endif
     return duo.f;
 }
 
 static CFISH_INLINE double
-lucy_NumUtil_decode_bigend_f64(void *source) {
+cfish_NumUtil_decode_bigend_f64(void *source) {
     union { double d; uint64_t u64; } duo;
     memcpy(&duo, source, sizeof(double));
 #ifdef CHY_LITTLE_END
-    duo.u64 = lucy_NumUtil_decode_bigend_u64(&duo.u64);
+    duo.u64 = cfish_NumUtil_decode_bigend_u64(&duo.u64);
 #endif
     return duo.d;
 }
 
-#define LUCY_NUMUTIL_C32_MAX_BYTES  ((sizeof(uint32_t) * 8 / 7) + 1) // 5
-#define LUCY_NUMUTIL_C64_MAX_BYTES ((sizeof(uint64_t) * 8 / 7) + 1)  // 10
+#define CFISH_NUMUTIL_C32_MAX_BYTES  ((sizeof(uint32_t) * 8 / 7) + 1) // 5
+#define CFISH_NUMUTIL_C64_MAX_BYTES ((sizeof(uint64_t) * 8 / 7) + 1)  // 10
 
 static CFISH_INLINE void
-lucy_NumUtil_encode_c32(uint32_t value, char **out_buf) {
-    uint8_t   buf[LUCY_NUMUTIL_C32_MAX_BYTES];
+cfish_NumUtil_encode_c32(uint32_t value, char **out_buf) {
+    uint8_t   buf[CFISH_NUMUTIL_C32_MAX_BYTES];
     uint8_t  *const limit = buf + sizeof(buf);
     uint8_t  *ptr         = limit - 1;
     int       num_bytes;
@@ -323,8 +323,8 @@ lucy_NumUtil_encode_c32(uint32_t value, char **out_buf) {
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_encode_c64(uint64_t value, char **out_buf) {
-    uint8_t   buf[LUCY_NUMUTIL_C64_MAX_BYTES];
+cfish_NumUtil_encode_c64(uint64_t value, char **out_buf) {
+    uint8_t   buf[CFISH_NUMUTIL_C64_MAX_BYTES];
     uint8_t  *const limit = buf + sizeof(buf);
     uint8_t  *ptr         = limit - 1;
     int       num_bytes;
@@ -342,8 +342,8 @@ lucy_NumUtil_encode_c64(uint64_t value, char **out_buf) {
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_encode_padded_c32(uint32_t value, char **out_buf) {
-    uint8_t buf[LUCY_NUMUTIL_C32_MAX_BYTES]
+cfish_NumUtil_encode_padded_c32(uint32_t value, char **out_buf) {
+    uint8_t buf[CFISH_NUMUTIL_C32_MAX_BYTES]
         = { 0x80, 0x80, 0x80, 0x80, 0x80 };
     uint8_t *const limit = buf + sizeof(buf);
     uint8_t *ptr         = limit - 1;
@@ -355,12 +355,12 @@ lucy_NumUtil_encode_padded_c32(uint32_t value, char **out_buf) {
         *--ptr = ((value & 0x7f) | 0x80);
         value >>= 7;
     }
-    memcpy(*out_buf, buf, LUCY_NUMUTIL_C32_MAX_BYTES);
+    memcpy(*out_buf, buf, CFISH_NUMUTIL_C32_MAX_BYTES);
     *out_buf += sizeof(buf);
 }
 
 // Decode a compressed integer up to size of 'var', advancing 'source'
-#define LUCY_NUMUTIL_DECODE_CINT(var, source) \
+#define CFISH_NUMUTIL_DECODE_CINT(var, source) \
     do { \
         var = (*source & 0x7f); \
         while (*source++ & 0x80) { \
@@ -369,76 +369,76 @@ lucy_NumUtil_encode_padded_c32(uint32_t value, char **out_buf) {
     } while (0)
 
 static CFISH_INLINE uint32_t
-lucy_NumUtil_decode_c32(char **source_ptr) {
+cfish_NumUtil_decode_c32(char **source_ptr) {
     char *source = *source_ptr;
     uint32_t decoded;
-    LUCY_NUMUTIL_DECODE_CINT(decoded, source);
+    CFISH_NUMUTIL_DECODE_CINT(decoded, source);
     *source_ptr = source;
     return decoded;
 }
 
 static CFISH_INLINE uint64_t
-lucy_NumUtil_decode_c64(char **source_ptr) {
+cfish_NumUtil_decode_c64(char **source_ptr) {
     char *source = *source_ptr;
     uint64_t decoded;
-    LUCY_NUMUTIL_DECODE_CINT(decoded, source);
+    CFISH_NUMUTIL_DECODE_CINT(decoded, source);
     *source_ptr = source;
     return decoded;
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_skip_cint(char **source_ptr) {
+cfish_NumUtil_skip_cint(char **source_ptr) {
     uint8_t *ptr = *(uint8_t**)source_ptr;
     while ((*ptr++ & 0x80) != 0) { }
     *source_ptr = (char*)ptr;
 }
 
 static CFISH_INLINE bool
-lucy_NumUtil_u1get(void *array, uint32_t tick) {
+cfish_NumUtil_u1get(void *array, uint32_t tick) {
     uint8_t *const u8bits      = (uint8_t*)array;
     const uint32_t byte_offset = tick >> 3;
-    const uint8_t  mask        = lucy_NumUtil_u1masks[tick & 0x7];
+    const uint8_t  mask        = cfish_NumUtil_u1masks[tick & 0x7];
     return !((u8bits[byte_offset] & mask) == 0);
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_u1set(void *array, uint32_t tick) {
+cfish_NumUtil_u1set(void *array, uint32_t tick) {
     uint8_t *const u8bits      = (uint8_t*)array;
     const uint32_t byte_offset = tick >> 3;
-    const uint8_t  mask        = lucy_NumUtil_u1masks[tick & 0x7];
+    const uint8_t  mask        = cfish_NumUtil_u1masks[tick & 0x7];
     u8bits[byte_offset] |= mask;
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_u1clear(void *array, uint32_t tick) {
+cfish_NumUtil_u1clear(void *array, uint32_t tick) {
     uint8_t *const u8bits      = (uint8_t*)array;
     const uint32_t byte_offset = tick >> 3;
-    const uint8_t  mask        = lucy_NumUtil_u1masks[tick & 0x7];
+    const uint8_t  mask        = cfish_NumUtil_u1masks[tick & 0x7];
     u8bits[byte_offset] &= ~mask;
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_u1flip(void *array, uint32_t tick) {
+cfish_NumUtil_u1flip(void *array, uint32_t tick) {
     uint8_t *const u8bits      = (uint8_t*)array;
     const uint32_t byte_offset = tick >> 3;
-    const uint8_t  mask        = lucy_NumUtil_u1masks[tick & 0x7];
+    const uint8_t  mask        = cfish_NumUtil_u1masks[tick & 0x7];
     u8bits[byte_offset] ^= mask;
 }
 
 static CFISH_INLINE uint8_t
-lucy_NumUtil_u2get(void *array, uint32_t tick) {
+cfish_NumUtil_u2get(void *array, uint32_t tick) {
     uint8_t *ints  = (uint8_t*)array;
     uint8_t  byte  = ints[(tick >> 2)];
-    int      shift = lucy_NumUtil_u2shifts[tick & 0x3];
+    int      shift = cfish_NumUtil_u2shifts[tick & 0x3];
     return (byte >> shift) & 0x3;
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_u2set(void *array, uint32_t tick, uint8_t value) {
+cfish_NumUtil_u2set(void *array, uint32_t tick, uint8_t value) {
     uint8_t *ints     = (uint8_t*)array;
     unsigned sub_tick = tick & 0x3;
-    int      shift    = lucy_NumUtil_u2shifts[sub_tick];
-    uint8_t  mask     = lucy_NumUtil_u2masks[sub_tick];
+    int      shift    = cfish_NumUtil_u2shifts[sub_tick];
+    uint8_t  mask     = cfish_NumUtil_u2masks[sub_tick];
     uint8_t  new_val  = value & 0x3;
     uint8_t  new_bits = new_val << shift;
     ints[(tick >> 2)]  = (ints[(tick >> 2)] & ~mask) | new_bits;
@@ -446,27 +446,27 @@ lucy_NumUtil_u2set(void *array, uint32_t tick, uint8_t value) {
 
 
 static CFISH_INLINE uint8_t
-lucy_NumUtil_u4get(void *array, uint32_t tick) {
+cfish_NumUtil_u4get(void *array, uint32_t tick) {
     uint8_t *ints  = (uint8_t*)array;
     uint8_t  byte  = ints[(tick >> 1)];
-    int      shift = lucy_NumUtil_u4shifts[(tick & 1)];
+    int      shift = cfish_NumUtil_u4shifts[(tick & 1)];
     return (byte >> shift) & 0xF;
 }
 
 static CFISH_INLINE void
-lucy_NumUtil_u4set(void *array, uint32_t tick, uint8_t value) {
+cfish_NumUtil_u4set(void *array, uint32_t tick, uint8_t value) {
     uint8_t  *ints     = (uint8_t*)array;
     unsigned  sub_tick = tick & 0x1;
-    int       shift    = lucy_NumUtil_u4shifts[sub_tick];
-    uint8_t   mask     = lucy_NumUtil_u4masks[sub_tick];
+    int       shift    = cfish_NumUtil_u4shifts[sub_tick];
+    uint8_t   mask     = cfish_NumUtil_u4masks[sub_tick];
     uint8_t   new_val  = value & 0xF;
     uint8_t   new_bits = new_val << shift;
     ints[(tick >> 1)]  = (ints[(tick >> 1)] & ~mask) | new_bits;
 }
 
 #ifdef LUCY_USE_SHORT_NAMES
-  #define C32_MAX_BYTES                LUCY_NUMUTIL_C32_MAX_BYTES
-  #define C64_MAX_BYTES                LUCY_NUMUTIL_C64_MAX_BYTES
+  #define C32_MAX_BYTES                CFISH_NUMUTIL_C32_MAX_BYTES
+  #define C64_MAX_BYTES                CFISH_NUMUTIL_C64_MAX_BYTES
 #endif
 
 __END_C__

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Util/SortUtils.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/SortUtils.c b/core/Clownfish/Util/SortUtils.c
index 3b17077..18eb88d 100644
--- a/core/Clownfish/Util/SortUtils.c
+++ b/core/Clownfish/Util/SortUtils.c
@@ -33,22 +33,22 @@
 // Recursive merge sorting functions.
 static void
 S_msort4(void *velems, void *vscratch, uint32_t left, uint32_t right,
-         Lucy_Sort_Compare_t compare, void *context);
+         Cfish_Sort_Compare_t compare, void *context);
 static void
 S_msort8(void *velems, void *vscratch, uint32_t left, uint32_t right,
-         Lucy_Sort_Compare_t compare, void *context);
+         Cfish_Sort_Compare_t compare, void *context);
 static void
 S_msort_any(void *velems, void *vscratch, uint32_t left, uint32_t right,
-            Lucy_Sort_Compare_t compare, void *context, size_t width);
+            Cfish_Sort_Compare_t compare, void *context, size_t width);
 
 static INLINE void
 SI_merge(void *left_vptr,  uint32_t left_size,
          void *right_vptr, uint32_t right_size,
-         void *vdest, size_t width, Lucy_Sort_Compare_t compare, void *context);
+         void *vdest, size_t width, Cfish_Sort_Compare_t compare, void *context);
 
 void
 Sort_mergesort(void *elems, void *scratch, uint32_t num_elems, uint32_t width,
-               Lucy_Sort_Compare_t compare, void *context) {
+               Cfish_Sort_Compare_t compare, void *context) {
     // Arrays of 0 or 1 items are already sorted.
     if (num_elems < 2) { return; }
 
@@ -79,7 +79,7 @@ Sort_mergesort(void *elems, void *scratch, uint32_t num_elems, uint32_t width,
 void
 Sort_merge(void *left_ptr,  uint32_t left_size,
            void *right_ptr, uint32_t right_size,
-           void *dest, size_t width, Lucy_Sort_Compare_t compare,
+           void *dest, size_t width, Cfish_Sort_Compare_t compare,
            void *context) {
     switch (width) {
         case 0:
@@ -103,7 +103,7 @@ Sort_merge(void *left_ptr,  uint32_t left_size,
 #define WIDTH 4
 static void
 S_msort4(void *velems, void *vscratch, uint32_t left, uint32_t right,
-         Lucy_Sort_Compare_t compare, void *context) {
+         Cfish_Sort_Compare_t compare, void *context) {
     uint8_t *elems   = (uint8_t*)velems;
     uint8_t *scratch = (uint8_t*)vscratch;
     if (right > left) {
@@ -121,7 +121,7 @@ S_msort4(void *velems, void *vscratch, uint32_t left, uint32_t right,
 #define WIDTH 8
 static void
 S_msort8(void *velems, void *vscratch, uint32_t left, uint32_t right,
-         Lucy_Sort_Compare_t compare, void *context) {
+         Cfish_Sort_Compare_t compare, void *context) {
     uint8_t *elems   = (uint8_t*)velems;
     uint8_t *scratch = (uint8_t*)vscratch;
     if (right > left) {
@@ -138,7 +138,7 @@ S_msort8(void *velems, void *vscratch, uint32_t left, uint32_t right,
 #undef WIDTH
 static void
 S_msort_any(void *velems, void *vscratch, uint32_t left, uint32_t right,
-            Lucy_Sort_Compare_t compare, void *context, size_t width) {
+            Cfish_Sort_Compare_t compare, void *context, size_t width) {
     uint8_t *elems   = (uint8_t*)velems;
     uint8_t *scratch = (uint8_t*)vscratch;
     if (right > left) {
@@ -155,7 +155,7 @@ S_msort_any(void *velems, void *vscratch, uint32_t left, uint32_t right,
 static INLINE void
 SI_merge(void *left_vptr,  uint32_t left_size,
          void *right_vptr, uint32_t right_size,
-         void *vdest, size_t width, Lucy_Sort_Compare_t compare,
+         void *vdest, size_t width, Cfish_Sort_Compare_t compare,
          void *context) {
     uint8_t *left_ptr    = (uint8_t*)left_vptr;
     uint8_t *right_ptr   = (uint8_t*)right_vptr;
@@ -188,10 +188,10 @@ SI_merge(void *left_vptr,  uint32_t left_size,
 // Quicksort implementations optimized for four-byte and eight-byte elements.
 static void
 S_qsort4(FOUR_BYTE_TYPE *elems, int32_t left, int32_t right,
-         Lucy_Sort_Compare_t compare, void *context);
+         Cfish_Sort_Compare_t compare, void *context);
 static void
 S_qsort8(EIGHT_BYTE_TYPE *elems, int32_t left, int32_t right,
-         Lucy_Sort_Compare_t compare, void *context);
+         Cfish_Sort_Compare_t compare, void *context);
 
 // Swap two elements.
 static INLINE void
@@ -221,14 +221,14 @@ SI_exchange8(EIGHT_BYTE_TYPE *elems, int32_t left, int32_t right);
  */
 static INLINE FOUR_BYTE_TYPE*
 SI_choose_pivot4(FOUR_BYTE_TYPE *elems, int32_t left, int32_t right,
-                 Lucy_Sort_Compare_t compare, void *context);
+                 Cfish_Sort_Compare_t compare, void *context);
 static INLINE EIGHT_BYTE_TYPE*
 SI_choose_pivot8(EIGHT_BYTE_TYPE *elems, int32_t left, int32_t right,
-                 Lucy_Sort_Compare_t compare, void *context);
+                 Cfish_Sort_Compare_t compare, void *context);
 
 void
 Sort_quicksort(void *elems, size_t num_elems, size_t width,
-               Lucy_Sort_Compare_t compare, void *context) {
+               Cfish_Sort_Compare_t compare, void *context) {
     // Arrays of 0 or 1 items are already sorted.
     if (num_elems < 2) { return; }
 
@@ -260,7 +260,7 @@ SI_exchange4(FOUR_BYTE_TYPE *elems, int32_t left, int32_t right) {
 
 static INLINE FOUR_BYTE_TYPE*
 SI_choose_pivot4(FOUR_BYTE_TYPE *elems, int32_t left, int32_t right,
-                 Lucy_Sort_Compare_t compare, void *context) {
+                 Cfish_Sort_Compare_t compare, void *context) {
     if (right - left > 1) {
         int32_t mid = left + (right - left) / 2;
         if (compare(context, elems + left, elems + mid) > 0) {
@@ -278,7 +278,7 @@ SI_choose_pivot4(FOUR_BYTE_TYPE *elems, int32_t left, int32_t right,
 
 static void
 S_qsort4(FOUR_BYTE_TYPE *elems, int32_t left, int32_t right,
-         Lucy_Sort_Compare_t compare, void *context) {
+         Cfish_Sort_Compare_t compare, void *context) {
     FOUR_BYTE_TYPE *const pivot
         = SI_choose_pivot4(elems, left, right, compare, context);
     int32_t i = left - 1;
@@ -365,7 +365,7 @@ SI_exchange8(EIGHT_BYTE_TYPE *elems, int32_t left, int32_t right) {
 
 static INLINE EIGHT_BYTE_TYPE*
 SI_choose_pivot8(EIGHT_BYTE_TYPE *elems, int32_t left, int32_t right,
-                 Lucy_Sort_Compare_t compare, void *context) {
+                 Cfish_Sort_Compare_t compare, void *context) {
     if (right - left > 1) {
         int32_t mid = left + (right - left) / 2;
         if (compare(context, elems + left, elems + mid) > 0) {
@@ -383,7 +383,7 @@ SI_choose_pivot8(EIGHT_BYTE_TYPE *elems, int32_t left, int32_t right,
 
 static void
 S_qsort8(EIGHT_BYTE_TYPE *elems, int32_t left, int32_t right,
-         Lucy_Sort_Compare_t compare, void *context) {
+         Cfish_Sort_Compare_t compare, void *context) {
     EIGHT_BYTE_TYPE *const pivot
         = SI_choose_pivot8(elems, left, right, compare, context);
     int32_t i = left - 1;

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Util/SortUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/SortUtils.cfh b/core/Clownfish/Util/SortUtils.cfh
index 4071a32..7667e81 100644
--- a/core/Clownfish/Util/SortUtils.cfh
+++ b/core/Clownfish/Util/SortUtils.cfh
@@ -18,7 +18,7 @@ parcel Lucy;
 
 __C__
 typedef int
-(*Lucy_Sort_Compare_t)(void *context, const void *va, const void *vb);
+(*Cfish_Sort_Compare_t)(void *context, const void *va, const void *vb);
 __END_C__
 
 /** Specialized sorting routines.
@@ -38,7 +38,7 @@ inert class Clownfish::Util::SortUtils cnick Sort {
      */
     inert void
     mergesort(void *elems, void *scratch, uint32_t num_elems, uint32_t width,
-              Lucy_Sort_Compare_t compare, void *context);
+              Cfish_Sort_Compare_t compare, void *context);
 
     /** Merge two source arrays together using the classic mergesort merge
      * algorithm, storing the result in <code>dest</code>.
@@ -56,13 +56,13 @@ inert class Clownfish::Util::SortUtils cnick Sort {
     inert void
     merge(void *left_ptr,  uint32_t left_num_elems,
           void *right_ptr, uint32_t right_num_elems,
-          void *dest, size_t width, Lucy_Sort_Compare_t compare, void *context);
+          void *dest, size_t width, Cfish_Sort_Compare_t compare, void *context);
 
     /** Quicksort.
      */
     inert void
     quicksort(void *elems, size_t num_elems, size_t width,
-              Lucy_Sort_Compare_t compare, void *context);
+              Cfish_Sort_Compare_t compare, void *context);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Util/StringHelper.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/StringHelper.c b/core/Clownfish/Util/StringHelper.c
index 58f278d..7726f9d 100644
--- a/core/Clownfish/Util/StringHelper.c
+++ b/core/Clownfish/Util/StringHelper.c
@@ -24,7 +24,7 @@
 #include "Clownfish/Err.h"
 #include "Clownfish/Util/Memory.h"
 
-const uint8_t lucy_StrHelp_UTF8_COUNT[] = {
+const uint8_t cfish_StrHelp_UTF8_COUNT[] = {
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/Util/StringHelper.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/StringHelper.cfh b/core/Clownfish/Util/StringHelper.cfh
index 60d6d78..9d7f4e0 100644
--- a/core/Clownfish/Util/StringHelper.cfh
+++ b/core/Clownfish/Util/StringHelper.cfh
@@ -74,9 +74,9 @@ __C__
 /** The maximum number of bytes encoded by to_base36(), including the
  * terminating NULL.
  */
-#define lucy_StrHelp_MAX_BASE36_BYTES 14
+#define cfish_StrHelp_MAX_BASE36_BYTES 14
 #ifdef LUCY_USE_SHORT_NAMES
-  #define StrHelp_MAX_BASE36_BYTES lucy_StrHelp_MAX_BASE36_BYTES
+  #define StrHelp_MAX_BASE36_BYTES cfish_StrHelp_MAX_BASE36_BYTES
 #endif
 __END_C__
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/VArray.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/VArray.c b/core/Clownfish/VArray.c
index 08314cf..7da0d33 100644
--- a/core/Clownfish/VArray.c
+++ b/core/Clownfish/VArray.c
@@ -307,7 +307,7 @@ S_default_compare(void *context, const void *va, const void *vb) {
 }
 
 void
-VA_sort(VArray *self, Lucy_Sort_Compare_t compare, void *context) {
+VA_sort(VArray *self, Cfish_Sort_Compare_t compare, void *context) {
     if (!compare) { compare = S_default_compare; }
     Sort_quicksort(self->elems, self->size, sizeof(void*), compare, context);
 }
@@ -332,7 +332,7 @@ VA_equals(VArray *self, Obj *other) {
 }
 
 VArray*
-VA_gather(VArray *self, Lucy_VA_Gather_Test_t test, void *data) {
+VA_gather(VArray *self, VA_Gather_Test_t test, void *data) {
     VArray *gathered = VA_new(self->size);
     for (uint32_t i = 0, max = self->size; i < max; i++) {
         if (test(self, i, data)) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/VArray.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/VArray.cfh b/core/Clownfish/VArray.cfh
index e6f8741..f36e31d 100644
--- a/core/Clownfish/VArray.cfh
+++ b/core/Clownfish/VArray.cfh
@@ -20,10 +20,10 @@ __C__
 #include "Clownfish/Util/SortUtils.h"
 
 typedef bool
-(*Lucy_VA_Gather_Test_t)(lucy_VArray *self, uint32_t tick, void *data);
+(*Cfish_VA_Gather_Test_t)(cfish_VArray *self, uint32_t tick, void *data);
 
 #ifdef LUCY_USE_SHORT_NAMES
-  #define Lucy_VA_Gather_Test_t Lucy_VA_Gather_Test_t
+  #define VA_Gather_Test_t Cfish_VA_Gather_Test_t
 #endif
 __END_C__
 
@@ -119,7 +119,7 @@ class Clownfish::VArray cnick VA inherits Clownfish::Obj {
      * @param context Argument supplied to the comparison routine.
      */
     void
-    Sort(VArray *self, Lucy_Sort_Compare_t compare = NULL,
+    Sort(VArray *self, Cfish_Sort_Compare_t compare = NULL,
          void *context = NULL);
 
     /** Set the size for the VArray.  If the new size is larger than the
@@ -147,7 +147,7 @@ class Clownfish::VArray cnick VA inherits Clownfish::Obj {
     /** Return all elements for which <code>test</code> returns true.
      */
     public incremented VArray*
-    Gather(VArray *self, Lucy_VA_Gather_Test_t test, void *data);
+    Gather(VArray *self, Cfish_VA_Gather_Test_t test, void *data);
 
     /** Return a new array consisting of elements from a contiguous slice.  If
      * the specified range is out of bounds, return an array with fewer

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Clownfish/VTable.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/VTable.c b/core/Clownfish/VTable.c
index 7abdb8e..dbc5715 100644
--- a/core/Clownfish/VTable.c
+++ b/core/Clownfish/VTable.c
@@ -278,7 +278,7 @@ VTable_singleton(const CharBuf *class_name, VTable *parent) {
 
 Obj*
 VTable_load_obj(VTable *self, Obj *dump) {
-    Obj_Load_t load = METHOD_PTR(self, Lucy_Obj_Load);
+    Obj_Load_t load = METHOD_PTR(self, Cfish_Obj_Load);
     if (load == Obj_load) {
         THROW(ERR, "Abstract method Load() not defined for %o", self->name);
     }

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Lucy/Plan/FieldType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Plan/FieldType.cfh b/core/Lucy/Plan/FieldType.cfh
index 7f3df32..bad2186 100644
--- a/core/Lucy/Plan/FieldType.cfh
+++ b/core/Lucy/Plan/FieldType.cfh
@@ -169,7 +169,7 @@ __C__
 
 static CFISH_INLINE int32_t
 lucy_FType_null_back_compare_values(lucy_FieldType *self,
-                                    lucy_Obj *a, lucy_Obj *b) {
+                                    cfish_Obj *a, cfish_Obj *b) {
     if (a == NULL) {
         if (b == NULL) { return 0; }
         else { return 1; }

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Lucy/Test.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test.cfh b/core/Lucy/Test.cfh
index 34775fa..661b6a0 100644
--- a/core/Lucy/Test.cfh
+++ b/core/Lucy/Test.cfh
@@ -28,14 +28,14 @@ inert class Lucy::Test {
 
 __C__
 #ifdef LUCY_USE_SHORT_NAMES
-  #define TEST_TRUE                    lucy_TestBatch_test_true
-  #define TEST_FALSE                   lucy_TestBatch_test_false
-  #define TEST_INT_EQ                  lucy_TestBatch_test_int_equals
-  #define TEST_FLOAT_EQ                lucy_TestBatch_test_float_equals
-  #define TEST_STR_EQ                  lucy_TestBatch_test_string_equals
-  #define PASS                         lucy_TestBatch_pass
-  #define FAIL                         lucy_TestBatch_fail
-  #define SKIP                         lucy_TestBatch_skip
+  #define TEST_TRUE                    cfish_TestBatch_test_true
+  #define TEST_FALSE                   cfish_TestBatch_test_false
+  #define TEST_INT_EQ                  cfish_TestBatch_test_int_equals
+  #define TEST_FLOAT_EQ                cfish_TestBatch_test_float_equals
+  #define TEST_STR_EQ                  cfish_TestBatch_test_string_equals
+  #define PASS                         cfish_TestBatch_pass
+  #define FAIL                         cfish_TestBatch_fail
+  #define SKIP                         cfish_TestBatch_skip
 #endif
 __END_C__
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Lucy/Test/Index/TestTermInfo.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestTermInfo.c b/core/Lucy/Test/Index/TestTermInfo.c
index c6f996b..9de3a08 100644
--- a/core/Lucy/Test/Index/TestTermInfo.c
+++ b/core/Lucy/Test/Index/TestTermInfo.c
@@ -42,7 +42,7 @@ test_freqfilepos(TestBatch *batch) {
 
     TermInfo* cloned_tinfo = TInfo_Clone(tinfo);
 
-    TEST_FALSE(batch, Lucy_TInfo_Equals(tinfo, (lucy_Obj*)cloned_tinfo),"the clone should be a separate C struct");
+    TEST_FALSE(batch, Lucy_TInfo_Equals(tinfo, (Obj*)cloned_tinfo),"the clone should be a separate C struct");
     TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(tinfo), 10, "new sets doc_freq correctly" );
     TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(tinfo), 10, "... doc_freq cloned" );
     TEST_INT_EQ(batch, TInfo_Get_Post_FilePos(tinfo), 20, "... post_filepos cloned" );

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Lucy/Util/Json.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Util/Json.c b/core/Lucy/Util/Json.c
index c0885c8..154c38d 100644
--- a/core/Lucy/Util/Json.c
+++ b/core/Lucy/Util/Json.c
@@ -30,7 +30,7 @@
 void*
 LucyParseJsonAlloc(void * (*allocate)(size_t));
 void
-LucyParseJson(void *json_parser, int token_type, lucy_Obj *value,
+LucyParseJson(void *json_parser, int token_type, Obj *value,
               lucy_JsonParserState *state);
 void
 LucyParseJsonFree(void *json_parser, void(*freemem)(void*));
@@ -368,14 +368,14 @@ S_to_json(Obj *dump, CharBuf *json, int32_t depth) {
 
 static Obj*
 S_parse_json(char *text, size_t size) {
-    void *json_parser = LucyParseJsonAlloc(lucy_Memory_wrapped_malloc);
+    void *json_parser = LucyParseJsonAlloc(Memory_wrapped_malloc);
     if (json_parser == NULL) {
         CharBuf *mess = MAKE_MESS("Failed to allocate JSON parser");
         Err_set_error(Err_new(mess));
         return NULL;
     }
     Obj *dump = S_do_parse_json(json_parser, text, size);
-    LucyParseJsonFree(json_parser, lucy_Memory_wrapped_free);
+    LucyParseJsonFree(json_parser, Memory_wrapped_free);
     return dump;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Lucy/Util/Json.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Util/Json.cfh b/core/Lucy/Util/Json.cfh
index 3dcd0a9..f872438 100644
--- a/core/Lucy/Util/Json.cfh
+++ b/core/Lucy/Util/Json.cfh
@@ -62,8 +62,8 @@ __C__
 
 struct lucy_JsonParserState 
 {
-    lucy_Obj   *result;
-    bool    errors;
+    cfish_Obj *result;
+    bool       errors;
 };
 typedef struct lucy_JsonParserState lucy_JsonParserState;
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/core/Lucy/Util/SortExternal.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Util/SortExternal.c b/core/Lucy/Util/SortExternal.c
index 4f530f7..1a220ed 100644
--- a/core/Lucy/Util/SortExternal.c
+++ b/core/Lucy/Util/SortExternal.c
@@ -125,8 +125,8 @@ SortEx_sort_cache(SortExternal *self) {
     }
     if (self->cache_max != 0) {
         VTable *vtable = SortEx_Get_VTable(self);
-        Lucy_Sort_Compare_t compare
-            = (Lucy_Sort_Compare_t)METHOD_PTR(vtable, Lucy_SortEx_Compare);
+        Cfish_Sort_Compare_t compare
+            = (Cfish_Sort_Compare_t)METHOD_PTR(vtable, Lucy_SortEx_Compare);
         if (self->scratch_cap < self->cache_cap) {
             self->scratch_cap = self->cache_cap;
             self->scratch = (uint8_t*)REALLOCATE(
@@ -219,8 +219,8 @@ S_absorb_slices(SortExternal *self, uint8_t *endpost) {
     uint8_t   **slice_starts = self->slice_starts;
     uint32_t   *slice_sizes  = self->slice_sizes;
     VTable     *vtable       = SortEx_Get_VTable(self);
-    Lucy_Sort_Compare_t compare
-        = (Lucy_Sort_Compare_t)METHOD_PTR(vtable, Lucy_SortEx_Compare);
+    Cfish_Sort_Compare_t compare
+        = (Cfish_Sort_Compare_t)METHOD_PTR(vtable, Lucy_SortEx_Compare);
 
     if (self->cache_max != 0) { THROW(ERR, "Can't refill unless empty"); }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/perl/buildlib/Lucy/Build/Binding/Object.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Object.pm b/perl/buildlib/Lucy/Build/Binding/Object.pm
index 8adbbfe..ba9f957 100644
--- a/perl/buildlib/Lucy/Build/Binding/Object.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Object.pm
@@ -333,7 +333,7 @@ CODE:
     }
     if (ints_av && SvTYPE(ints_av) == SVt_PVAV) {
         int32_t size  = av_len(ints_av) + 1;
-        int32_t *ints = (int32_t*)LUCY_MALLOCATE(size * sizeof(int32_t));
+        int32_t *ints = (int32_t*)CFISH_MALLOCATE(size * sizeof(int32_t));
         int32_t i;
 
         for (i = 0; i < size; i++) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/perl/buildlib/Lucy/Build/Binding/Util.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Util.pm b/perl/buildlib/Lucy/Build/Binding/Util.pm
index 6820869..237e93d 100644
--- a/perl/buildlib/Lucy/Build/Binding/Util.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Util.pm
@@ -221,7 +221,7 @@ to_base36(num)
     uint64_t num;
 CODE:
 {
-    char base36[lucy_StrHelp_MAX_BASE36_BYTES];
+    char base36[cfish_StrHelp_MAX_BASE36_BYTES];
     size_t size = lucy_StrHelp_to_base36(num, &base36);
     RETVAL = newSVpvn(base36, size);
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/perl/xs/Lucy/Analysis/RegexTokenizer.c
----------------------------------------------------------------------
diff --git a/perl/xs/Lucy/Analysis/RegexTokenizer.c b/perl/xs/Lucy/Analysis/RegexTokenizer.c
index e386cf6..211e461 100644
--- a/perl/xs/Lucy/Analysis/RegexTokenizer.c
+++ b/perl/xs/Lucy/Analysis/RegexTokenizer.c
@@ -127,7 +127,7 @@ void
 lucy_RegexTokenizer_destroy(lucy_RegexTokenizer *self) {
     CFISH_DECREF(self->pattern);
     ReREFCNT_dec(((REGEXP*)self->token_re));
-    LUCY_SUPER_DESTROY(self, LUCY_REGEXTOKENIZER);
+    CFISH_SUPER_DESTROY(self, LUCY_REGEXTOKENIZER);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/perl/xs/Lucy/Document/Doc.c
----------------------------------------------------------------------
diff --git a/perl/xs/Lucy/Document/Doc.c b/perl/xs/Lucy/Document/Doc.c
index 0f0de76..aa3e4df 100644
--- a/perl/xs/Lucy/Document/Doc.c
+++ b/perl/xs/Lucy/Document/Doc.c
@@ -237,7 +237,7 @@ lucy_Doc_equals(lucy_Doc *self, lucy_Obj *other) {
 void
 lucy_Doc_destroy(lucy_Doc *self) {
     if (self->fields) { SvREFCNT_dec((SV*)self->fields); }
-    LUCY_SUPER_DESTROY(self, LUCY_DOC);
+    CFISH_SUPER_DESTROY(self, LUCY_DOC);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/6cfc6291/perl/xs/XSBind.c
----------------------------------------------------------------------
diff --git a/perl/xs/XSBind.c b/perl/xs/XSBind.c
index 3261069..8352355 100644
--- a/perl/xs/XSBind.c
+++ b/perl/xs/XSBind.c
@@ -542,7 +542,7 @@ XSBind_allot_params(SV** stack, int32_t start, int32_t num_stack_elems, ...) {
             if (SvCUR(key_sv) == (STRLEN)label_len) {
                 if (memcmp(SvPVX(key_sv), label, label_len) == 0) {
                     found_arg = tick;
-                    lucy_NumUtil_u1set(verified_labels, tick);
+                    cfish_NumUtil_u1set(verified_labels, tick);
                 }
             }
         }
@@ -573,7 +573,7 @@ XSBind_allot_params(SV** stack, int32_t start, int32_t num_stack_elems, ...) {
 
     // Ensure that all parameter labels were valid.
     for (int32_t tick = start; tick < num_stack_elems; tick += 2) {
-        if (!lucy_NumUtil_u1get(verified_labels, tick)) {
+        if (!cfish_NumUtil_u1get(verified_labels, tick)) {
             SV *const key_sv = stack[tick];
             char *key = SvPV_nolen(key_sv);
             cfish_CharBuf *mess
@@ -594,7 +594,7 @@ XSBind_allot_params(SV** stack, int32_t start, int32_t num_stack_elems, ...) {
 /**************************** Clownfish::Obj *******************************/
 
 static void
-S_lazy_init_host_obj(lucy_Obj *self) {
+S_lazy_init_host_obj(cfish_Obj *self) {
     SV *inner_obj = newSV(0);
     SvOBJECT_on(inner_obj);
 #if (PERL_VERSION <= 16)
@@ -604,9 +604,9 @@ S_lazy_init_host_obj(lucy_Obj *self) {
     sv_setiv(inner_obj, PTR2IV(self));
 
     // Connect class association.
-    lucy_CharBuf *class_name = Lucy_VTable_Get_Name(self->vtable);
-    HV *stash = gv_stashpvn((char*)Lucy_CB_Get_Ptr8(class_name),
-                            Lucy_CB_Get_Size(class_name), TRUE);
+    cfish_CharBuf *class_name = Cfish_VTable_Get_Name(self->vtable);
+    HV *stash = gv_stashpvn((char*)Cfish_CB_Get_Ptr8(class_name),
+                            Cfish_CB_Get_Size(class_name), TRUE);
     SvSTASH_set(inner_obj, (HV*)SvREFCNT_inc(stash));
 
     /* Up till now we've been keeping track of the refcount in
@@ -620,17 +620,17 @@ S_lazy_init_host_obj(lucy_Obj *self) {
 }
 
 uint32_t
-lucy_Obj_get_refcount(lucy_Obj *self) {
+cfish_Obj_get_refcount(cfish_Obj *self) {
     return self->ref.count & XSBIND_REFCOUNT_FLAG
            ? self->ref.count >> XSBIND_REFCOUNT_SHIFT
            : SvREFCNT((SV*)self->ref.host_obj);
 }
 
-lucy_Obj*
-lucy_Obj_inc_refcount(lucy_Obj *self) {
+cfish_Obj*
+cfish_Obj_inc_refcount(cfish_Obj *self) {
     if (self->ref.count & XSBIND_REFCOUNT_FLAG) {
         if (self->ref.count == XSBIND_REFCOUNT_FLAG) {
-            CFISH_THROW(LUCY_ERR, "Illegal refcount of 0");
+            CFISH_THROW(CFISH_ERR, "Illegal refcount of 0");
         }
         self->ref.count += 1 << XSBIND_REFCOUNT_SHIFT;
     }
@@ -641,16 +641,16 @@ lucy_Obj_inc_refcount(lucy_Obj *self) {
 }
 
 uint32_t
-lucy_Obj_dec_refcount(lucy_Obj *self) {
+cfish_Obj_dec_refcount(cfish_Obj *self) {
     uint32_t modified_refcount = I32_MAX;
     if (self->ref.count & XSBIND_REFCOUNT_FLAG) {
         if (self->ref.count == XSBIND_REFCOUNT_FLAG) {
-            CFISH_THROW(LUCY_ERR, "Illegal refcount of 0");
+            CFISH_THROW(CFISH_ERR, "Illegal refcount of 0");
         }
         if (self->ref.count
             == ((1 << XSBIND_REFCOUNT_SHIFT) | XSBIND_REFCOUNT_FLAG)) {
             modified_refcount = 0;
-            Lucy_Obj_Destroy(self);
+            Cfish_Obj_Destroy(self);
         }
         else {
             self->ref.count -= 1 << XSBIND_REFCOUNT_SHIFT;
@@ -667,34 +667,34 @@ lucy_Obj_dec_refcount(lucy_Obj *self) {
 }
 
 void*
-lucy_Obj_to_host(lucy_Obj *self) {
+cfish_Obj_to_host(cfish_Obj *self) {
     if (self->ref.count & XSBIND_REFCOUNT_FLAG) { S_lazy_init_host_obj(self); }
     return newRV_inc((SV*)self->ref.host_obj);
 }
 
 /*************************** Clownfish::VTable ******************************/
 
-lucy_Obj*
-lucy_VTable_make_obj(lucy_VTable *self) {
-    lucy_Obj *obj
-        = (lucy_Obj*)lucy_Memory_wrapped_calloc(self->obj_alloc_size, 1);
+cfish_Obj*
+cfish_VTable_make_obj(cfish_VTable *self) {
+    cfish_Obj *obj
+        = (cfish_Obj*)cfish_Memory_wrapped_calloc(self->obj_alloc_size, 1);
     obj->vtable = self;
     obj->ref.count = (1 << XSBIND_REFCOUNT_SHIFT) | XSBIND_REFCOUNT_FLAG;
     return obj;
 }
 
-lucy_Obj*
-lucy_VTable_init_obj(lucy_VTable *self, void *allocation) {
-    lucy_Obj *obj = (lucy_Obj*)allocation;
+cfish_Obj*
+cfish_VTable_init_obj(cfish_VTable *self, void *allocation) {
+    cfish_Obj *obj = (cfish_Obj*)allocation;
     obj->vtable = self;
     obj->ref.count = (1 << XSBIND_REFCOUNT_SHIFT) | XSBIND_REFCOUNT_FLAG;
     return obj;
 }
 
-lucy_Obj*
-lucy_VTable_foster_obj(lucy_VTable *self, void *host_obj) {
-    lucy_Obj *obj
-        = (lucy_Obj*)lucy_Memory_wrapped_calloc(self->obj_alloc_size, 1);
+cfish_Obj*
+cfish_VTable_foster_obj(cfish_VTable *self, void *host_obj) {
+    cfish_Obj *obj
+        = (cfish_Obj*)cfish_Memory_wrapped_calloc(self->obj_alloc_size, 1);
     SV *inner_obj = SvRV((SV*)host_obj);
     obj->vtable = self;
     sv_setiv(inner_obj, PTR2IV(obj));
@@ -703,22 +703,22 @@ lucy_VTable_foster_obj(lucy_VTable *self, void *host_obj) {
 }
 
 void
-lucy_VTable_register_with_host(lucy_VTable *singleton, lucy_VTable *parent) {
+cfish_VTable_register_with_host(cfish_VTable *singleton, cfish_VTable *parent) {
     dSP;
     ENTER;
     SAVETMPS;
     EXTEND(SP, 2);
     PUSHMARK(SP);
-    mPUSHs((SV*)Lucy_VTable_To_Host(singleton));
-    mPUSHs((SV*)Lucy_VTable_To_Host(parent));
+    mPUSHs((SV*)Cfish_VTable_To_Host(singleton));
+    mPUSHs((SV*)Cfish_VTable_To_Host(parent));
     PUTBACK;
     call_pv("Clownfish::VTable::_register", G_VOID | G_DISCARD);
     FREETMPS;
     LEAVE;
 }
 
-lucy_VArray*
-lucy_VTable_fresh_host_methods(const lucy_CharBuf *class_name) {
+cfish_VArray*
+cfish_VTable_fresh_host_methods(const cfish_CharBuf *class_name) {
     dSP;
     ENTER;
     SAVETMPS;
@@ -735,8 +735,8 @@ lucy_VTable_fresh_host_methods(const lucy_CharBuf *class_name) {
     return methods;
 }
 
-lucy_CharBuf*
-lucy_VTable_find_parent_class(const lucy_CharBuf *class_name) {
+cfish_CharBuf*
+cfish_VTable_find_parent_class(const cfish_CharBuf *class_name) {
     dSP;
     ENTER;
     SAVETMPS;
@@ -756,10 +756,10 @@ lucy_VTable_find_parent_class(const lucy_CharBuf *class_name) {
 }
 
 void*
-lucy_VTable_to_host(lucy_VTable *self) {
+cfish_VTable_to_host(cfish_VTable *self) {
     bool first_time = self->ref.count & XSBIND_REFCOUNT_FLAG ? true : false;
-    Lucy_VTable_To_Host_t to_host
-        = CFISH_SUPER_METHOD_PTR(LUCY_VTABLE, Lucy_VTable_To_Host);
+    Cfish_VTable_To_Host_t to_host
+        = CFISH_SUPER_METHOD_PTR(CFISH_VTABLE, Cfish_VTable_To_Host);
     SV *host_obj = (SV*)to_host(self);
     if (first_time) {
         SvSHARE((SV*)self->ref.host_obj);
@@ -774,7 +774,7 @@ lucy_VTable_to_host(lucy_VTable *self) {
 // so that it can be run inside a Perl eval block.
 static SV *attempt_xsub = NULL;
 
-XS(lucy_Err_attempt_via_xs) {
+XS(cfish_Err_attempt_via_xs) {
     dXSARGS;
     CHY_UNUSED_VAR(cv);
     SP -= items;
@@ -790,13 +790,13 @@ XS(lucy_Err_attempt_via_xs) {
 }
 
 void
-lucy_Err_init_class(void) {
+cfish_Err_init_class(void) {
     char *file = (char*)__FILE__;
-    attempt_xsub = (SV*)newXS(NULL, lucy_Err_attempt_via_xs, file);
+    attempt_xsub = (SV*)newXS(NULL, cfish_Err_attempt_via_xs, file);
 }
 
-lucy_Err*
-lucy_Err_get_error() {
+cfish_Err*
+cfish_Err_get_error() {
     dSP;
     ENTER;
     SAVETMPS;
@@ -812,7 +812,7 @@ lucy_Err_get_error() {
 }
 
 void
-lucy_Err_set_error(lucy_Err *error) {
+cfish_Err_set_error(cfish_Err *error) {
     dSP;
     ENTER;
     SAVETMPS;
@@ -820,7 +820,7 @@ lucy_Err_set_error(lucy_Err *error) {
     PUSHMARK(SP);
     PUSHmortal;
     if (error) {
-        mPUSHs((SV*)Lucy_Err_To_Host(error));
+        mPUSHs((SV*)Cfish_Err_To_Host(error));
     }
     else {
         PUSHmortal;
@@ -832,9 +832,9 @@ lucy_Err_set_error(lucy_Err *error) {
 }
 
 void
-lucy_Err_do_throw(lucy_Err *err) {
+cfish_Err_do_throw(cfish_Err *err) {
     dSP;
-    SV *error_sv = (SV*)Lucy_Err_To_Host(err);
+    SV *error_sv = (SV*)Cfish_Err_To_Host(err);
     CFISH_DECREF(err);
     ENTER;
     SAVETMPS;
@@ -847,35 +847,35 @@ lucy_Err_do_throw(lucy_Err *err) {
 }
 
 void*
-lucy_Err_to_host(lucy_Err *self) {
-    Lucy_Err_To_Host_t super_to_host
-        = CFISH_SUPER_METHOD_PTR(LUCY_ERR, Lucy_Err_To_Host);
+cfish_Err_to_host(cfish_Err *self) {
+    Cfish_Err_To_Host_t super_to_host
+        = CFISH_SUPER_METHOD_PTR(CFISH_ERR, Cfish_Err_To_Host);
     SV *perl_obj = (SV*)super_to_host(self);
     XSBind_enable_overload(perl_obj);
     return perl_obj;
 }
 
 void
-lucy_Err_throw_mess(lucy_VTable *vtable, lucy_CharBuf *message) {
-    Lucy_Err_Make_t make
-        = CFISH_METHOD_PTR(CFISH_CERTIFY(vtable, LUCY_VTABLE), Lucy_Err_Make);
-    lucy_Err *err = (lucy_Err*)CFISH_CERTIFY(make(NULL), LUCY_ERR);
-    Lucy_Err_Cat_Mess(err, message);
+cfish_Err_throw_mess(cfish_VTable *vtable, cfish_CharBuf *message) {
+    Cfish_Err_Make_t make
+        = CFISH_METHOD_PTR(CFISH_CERTIFY(vtable, CFISH_VTABLE), Cfish_Err_Make);
+    cfish_Err *err = (cfish_Err*)CFISH_CERTIFY(make(NULL), CFISH_ERR);
+    Cfish_Err_Cat_Mess(err, message);
     CFISH_DECREF(message);
-    lucy_Err_do_throw(err);
+    cfish_Err_do_throw(err);
 }
 
 void
-lucy_Err_warn_mess(lucy_CharBuf *message) {
+cfish_Err_warn_mess(cfish_CharBuf *message) {
     SV *error_sv = XSBind_cb_to_sv(message);
     CFISH_DECREF(message);
     warn("%s", SvPV_nolen(error_sv));
     SvREFCNT_dec(error_sv);
 }
 
-lucy_Err*
-lucy_Err_trap(Cfish_Err_Attempt_t routine, void *context) {
-    lucy_Err *error = NULL;
+cfish_Err*
+cfish_Err_trap(Cfish_Err_Attempt_t routine, void *context) {
+    cfish_Err *error = NULL;
     SV *routine_sv = newSViv(PTR2IV(routine));
     SV *context_sv = newSViv(PTR2IV(context));
     dSP;
@@ -889,10 +889,10 @@ lucy_Err_trap(Cfish_Err_Attempt_t routine, void *context) {
 
     int count = call_sv(attempt_xsub, G_EVAL | G_DISCARD);
     if (count != 0) {
-        lucy_CharBuf *mess
-            = lucy_CB_newf("'attempt' returned too many values: %i32",
+        cfish_CharBuf *mess
+            = cfish_CB_newf("'attempt' returned too many values: %i32",
                            (int32_t)count);
-        error = lucy_Err_new(mess);
+        error = cfish_Err_new(mess);
     }
     else {
         SV *dollar_at = get_sv("@", FALSE);
@@ -901,14 +901,14 @@ lucy_Err_trap(Cfish_Err_Attempt_t routine, void *context) {
                 && sv_derived_from(dollar_at,"Clownfish::Err")
                ) {
                 IV error_iv = SvIV(SvRV(dollar_at));
-                error = INT2PTR(lucy_Err*, error_iv);
+                error = INT2PTR(cfish_Err*, error_iv);
                 CFISH_INCREF(error);
             }
             else {
                 STRLEN len;
                 char *ptr = SvPVutf8(dollar_at, len);
-                lucy_CharBuf *mess = lucy_CB_new_from_trusted_utf8(ptr, len);
-                error = lucy_Err_new(mess);
+                cfish_CharBuf *mess = cfish_CB_new_from_trusted_utf8(ptr, len);
+                error = cfish_Err_new(mess);
             }
         }
     }
@@ -921,10 +921,10 @@ lucy_Err_trap(Cfish_Err_Attempt_t routine, void *context) {
 /*********************** Clownfish::LockFreeRegistry ************************/
 
 void*
-lucy_LFReg_to_host(lucy_LockFreeRegistry *self) {
+cfish_LFReg_to_host(cfish_LockFreeRegistry *self) {
     bool first_time = self->ref.count & XSBIND_REFCOUNT_FLAG ? true : false;
-    Lucy_LFReg_To_Host_t to_host
-        = CFISH_SUPER_METHOD_PTR(LUCY_LOCKFREEREGISTRY, Lucy_LFReg_To_Host);
+    Cfish_LFReg_To_Host_t to_host
+        = CFISH_SUPER_METHOD_PTR(CFISH_LOCKFREEREGISTRY, Cfish_LFReg_To_Host);
     SV *host_obj = (SV*)to_host(self);
     if (first_time) {
         SvSHARE((SV*)self->ref.host_obj);


[lucy-commits] [23/26] Rework Clownfish test harness

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestHighlightWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestHighlightWriter.c b/core/Lucy/Test/Index/TestHighlightWriter.c
index 791da1b..9e7dcc5 100644
--- a/core/Lucy/Test/Index/TestHighlightWriter.c
+++ b/core/Lucy/Test/Index/TestHighlightWriter.c
@@ -18,26 +18,20 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestHighlightWriter.h"
 #include "Lucy/Index/HighlightWriter.h"
 
 TestHighlightWriter*
-TestHLWriter_new(TestFormatter *formatter) {
-    TestHighlightWriter *self = (TestHighlightWriter*)VTable_Make_Obj(TESTHIGHLIGHTWRITER);
-    return TestHLWriter_init(self, formatter);
-}
-
-TestHighlightWriter*
-TestHLWriter_init(TestHighlightWriter *self, TestFormatter *formatter) {
-    return (TestHighlightWriter*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestHLWriter_new() {
+    return (TestHighlightWriter*)VTable_Make_Obj(TESTHIGHLIGHTWRITER);
 }
 
 void
-TestHLWriter_run_tests(TestHighlightWriter *self) {
-    TestBatch *batch = (TestBatch*)self;
-    PASS(batch, "Placeholder");
+TestHLWriter_run(TestHighlightWriter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    PASS(runner, "Placeholder");
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestHighlightWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestHighlightWriter.cfh b/core/Lucy/Test/Index/TestHighlightWriter.cfh
index d761e38..cb8ce9f 100644
--- a/core/Lucy/Test/Index/TestHighlightWriter.cfh
+++ b/core/Lucy/Test/Index/TestHighlightWriter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestHighlightWriter cnick TestHLWriter
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestHighlightWriter*
-    new(TestFormatter *formatter);
-
-    inert TestHighlightWriter*
-    init(TestHighlightWriter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestHighlightWriter *self);
+    Run(TestHighlightWriter *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestIndexManager.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestIndexManager.c b/core/Lucy/Test/Index/TestIndexManager.c
index a856300..f878381 100644
--- a/core/Lucy/Test/Index/TestIndexManager.c
+++ b/core/Lucy/Test/Index/TestIndexManager.c
@@ -17,24 +17,18 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestIndexManager.h"
 #include "Lucy/Index/IndexManager.h"
 
 TestIndexManager*
-TestIxManager_new(TestFormatter *formatter) {
-    TestIndexManager *self = (TestIndexManager*)VTable_Make_Obj(TESTINDEXMANAGER);
-    return TestIxManager_init(self, formatter);
-}
-
-TestIndexManager*
-TestIxManager_init(TestIndexManager *self, TestFormatter *formatter) {
-    return (TestIndexManager*)TestBatch_init((TestBatch*)self, 34, formatter);
+TestIxManager_new() {
+    return (TestIndexManager*)VTable_Make_Obj(TESTINDEXMANAGER);
 }
 
 static void
-test_Choose_Sparse(TestBatch *batch) {
+test_Choose_Sparse(TestBatchRunner *runner) {
     IndexManager *manager = IxManager_new(NULL, NULL);
 
     for (uint32_t num_segs = 2; num_segs < 20; num_segs++) {
@@ -43,14 +37,14 @@ test_Choose_Sparse(TestBatch *batch) {
             I32Arr_Set(doc_counts, j, 1000);
         }
         uint32_t threshold = IxManager_Choose_Sparse(manager, doc_counts);
-        TEST_TRUE(batch, threshold != 1,
+        TEST_TRUE(runner, threshold != 1,
                   "Either don't merge, or merge two segments: %u segs, thresh %u",
                   (unsigned)num_segs, (unsigned)threshold);
 
         if (num_segs != 12 && num_segs != 13) {  // when 2 is correct
             I32Arr_Set(doc_counts, 0, 1);
             threshold = IxManager_Choose_Sparse(manager, doc_counts);
-            TEST_TRUE(batch, threshold != 2,
+            TEST_TRUE(runner, threshold != 2,
                       "Don't include big next seg: %u segs, thresh %u",
                       (unsigned)num_segs, (unsigned)threshold);
         }
@@ -62,8 +56,8 @@ test_Choose_Sparse(TestBatch *batch) {
 }
 
 void
-TestIxManager_run_tests(TestIndexManager *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Choose_Sparse(batch);
+TestIxManager_run(TestIndexManager *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 34);
+    test_Choose_Sparse(runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestIndexManager.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestIndexManager.cfh b/core/Lucy/Test/Index/TestIndexManager.cfh
index 105b833..5b2c2e1 100644
--- a/core/Lucy/Test/Index/TestIndexManager.cfh
+++ b/core/Lucy/Test/Index/TestIndexManager.cfh
@@ -20,12 +20,9 @@ class Lucy::Test::Index::TestIndexManager cnick TestIxManager
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestIndexManager*
-    new(TestFormatter *formatter);
-
-    inert TestIndexManager*
-    init(TestIndexManager *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestIndexManager *self);
+    Run(TestIndexManager *self, TestBatchRunner *runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestPolyReader.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPolyReader.c b/core/Lucy/Test/Index/TestPolyReader.c
index 2f8dfc5..21e3cf1 100644
--- a/core/Lucy/Test/Index/TestPolyReader.c
+++ b/core/Lucy/Test/Index/TestPolyReader.c
@@ -18,24 +18,18 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestPolyReader.h"
 #include "Lucy/Index/PolyReader.h"
 
 TestPolyReader*
-TestPolyReader_new(TestFormatter *formatter) {
-    TestPolyReader *self = (TestPolyReader*)VTable_Make_Obj(TESTPOLYREADER);
-    return TestPolyReader_init(self, formatter);
-}
-
-TestPolyReader*
-TestPolyReader_init(TestPolyReader *self, TestFormatter *formatter) {
-    return (TestPolyReader*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestPolyReader_new() {
+    return (TestPolyReader*)VTable_Make_Obj(TESTPOLYREADER);
 }
 
 static void
-test_sub_tick(TestBatch *batch) {
+test_sub_tick(TestBatchRunner *runner) {
     size_t num_segs = 255;
     int32_t *ints = (int32_t*)MALLOCATE(num_segs * sizeof(int32_t));
     size_t i;
@@ -46,14 +40,14 @@ test_sub_tick(TestBatch *batch) {
     for (i = 1; i < num_segs; i++) {
         if (PolyReader_sub_tick(offsets, i) != i - 1) { break; }
     }
-    TEST_INT_EQ(batch, i, num_segs, "got all sub_tick() calls right");
+    TEST_INT_EQ(runner, i, num_segs, "got all sub_tick() calls right");
     DECREF(offsets);
     FREEMEM(ints);
 }
 
 void
-TestPolyReader_run_tests(TestPolyReader *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_sub_tick(batch);
+TestPolyReader_run(TestPolyReader *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    test_sub_tick(runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestPolyReader.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPolyReader.cfh b/core/Lucy/Test/Index/TestPolyReader.cfh
index 36c957e..6c1c409 100644
--- a/core/Lucy/Test/Index/TestPolyReader.cfh
+++ b/core/Lucy/Test/Index/TestPolyReader.cfh
@@ -20,12 +20,9 @@ class Lucy::Test::Index::TestPolyReader
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPolyReader*
-    new(TestFormatter *formatter);
-
-    inert TestPolyReader*
-    init(TestPolyReader *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestPolyReader *self);
+    Run(TestPolyReader *self, TestBatchRunner *runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestPostingListWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPostingListWriter.c b/core/Lucy/Test/Index/TestPostingListWriter.c
index f393665..0b559dc 100644
--- a/core/Lucy/Test/Index/TestPostingListWriter.c
+++ b/core/Lucy/Test/Index/TestPostingListWriter.c
@@ -18,25 +18,19 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestPostingListWriter.h"
 
 TestPostingListWriter*
-TestPListWriter_new(TestFormatter *formatter) {
-    TestPostingListWriter *self = (TestPostingListWriter*)VTable_Make_Obj(TESTPOSTINGLISTWRITER);
-    return TestPListWriter_init(self, formatter);
-}
-
-TestPostingListWriter*
-TestPListWriter_init(TestPostingListWriter *self, TestFormatter *formatter) {
-    return (TestPostingListWriter*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestPListWriter_new() {
+    return (TestPostingListWriter*)VTable_Make_Obj(TESTPOSTINGLISTWRITER);
 }
 
 void
-TestPListWriter_run_tests(TestPostingListWriter *self) {
-    TestBatch *batch = (TestBatch*)self;
-    PASS(batch, "Placeholder");
+TestPListWriter_run(TestPostingListWriter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    PASS(runner, "Placeholder");
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestPostingListWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPostingListWriter.cfh b/core/Lucy/Test/Index/TestPostingListWriter.cfh
index 5c460bf..14ef955 100644
--- a/core/Lucy/Test/Index/TestPostingListWriter.cfh
+++ b/core/Lucy/Test/Index/TestPostingListWriter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestPostingListWriter cnick TestPListWriter
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPostingListWriter*
-    new(TestFormatter *formatter);
-
-    inert TestPostingListWriter*
-    init(TestPostingListWriter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestPostingListWriter *self);
+    Run(TestPostingListWriter *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestSegWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegWriter.c b/core/Lucy/Test/Index/TestSegWriter.c
index 1e26311..d67e866 100644
--- a/core/Lucy/Test/Index/TestSegWriter.c
+++ b/core/Lucy/Test/Index/TestSegWriter.c
@@ -18,26 +18,20 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestSegWriter.h"
 #include "Lucy/Index/SegWriter.h"
 
 TestSegWriter*
-TestSegWriter_new(TestFormatter *formatter) {
-    TestSegWriter *self = (TestSegWriter*)VTable_Make_Obj(TESTSEGWRITER);
-    return TestSegWriter_init(self, formatter);
-}
-
-TestSegWriter*
-TestSegWriter_init(TestSegWriter *self, TestFormatter *formatter) {
-    return (TestSegWriter*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestSegWriter_new() {
+    return (TestSegWriter*)VTable_Make_Obj(TESTSEGWRITER);
 }
 
 void
-TestSegWriter_run_tests(TestSegWriter *self) {
-    TestBatch *batch = (TestBatch*)self;
-    PASS(batch, "placeholder");
+TestSegWriter_run(TestSegWriter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    PASS(runner, "placeholder");
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestSegWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegWriter.cfh b/core/Lucy/Test/Index/TestSegWriter.cfh
index 1ca9eaa..1a6cf18 100644
--- a/core/Lucy/Test/Index/TestSegWriter.cfh
+++ b/core/Lucy/Test/Index/TestSegWriter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestSegWriter
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSegWriter*
-    new(TestFormatter *formatter);
-
-    inert TestSegWriter*
-    init(TestSegWriter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSegWriter *self);
+    Run(TestSegWriter *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestSegment.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegment.c b/core/Lucy/Test/Index/TestSegment.c
index f0a3596..f8547c9 100644
--- a/core/Lucy/Test/Index/TestSegment.c
+++ b/core/Lucy/Test/Index/TestSegment.c
@@ -18,25 +18,19 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestSegment.h"
 #include "Lucy/Index/Segment.h"
 #include "Lucy/Store/RAMFolder.h"
 
 TestSegment*
-TestSeg_new(TestFormatter *formatter) {
-    TestSegment *self = (TestSegment*)VTable_Make_Obj(TESTSEGMENT);
-    return TestSeg_init(self, formatter);
-}
-
-TestSegment*
-TestSeg_init(TestSegment *self, TestFormatter *formatter) {
-    return (TestSegment*)TestBatch_init((TestBatch*)self, 21, formatter);
+TestSeg_new() {
+    return (TestSegment*)VTable_Make_Obj(TESTSEGMENT);
 }
 
 static void
-test_fields(TestBatch *batch) {
+test_fields(TestBatchRunner *runner) {
     Segment *segment = Seg_new(1);
     ZombieCharBuf *foo = ZCB_WRAP_STR("foo", 3);
     ZombieCharBuf *bar = ZCB_WRAP_STR("bar", 3);
@@ -44,34 +38,34 @@ test_fields(TestBatch *batch) {
     int32_t field_num;
 
     field_num = Seg_Add_Field(segment, (CharBuf*)foo);
-    TEST_TRUE(batch, field_num == 1,
+    TEST_TRUE(runner, field_num == 1,
               "Add_Field returns field number, and field numbers start at 1");
     field_num = Seg_Add_Field(segment, (CharBuf*)bar);
-    TEST_TRUE(batch, field_num == 2, "add a second field");
+    TEST_TRUE(runner, field_num == 2, "add a second field");
     field_num = Seg_Add_Field(segment, (CharBuf*)foo);
-    TEST_TRUE(batch, field_num == 1,
+    TEST_TRUE(runner, field_num == 1,
               "Add_Field returns existing field number if field is already known");
 
-    TEST_TRUE(batch, ZCB_Equals(bar, (Obj*)Seg_Field_Name(segment, 2)),
+    TEST_TRUE(runner, ZCB_Equals(bar, (Obj*)Seg_Field_Name(segment, 2)),
               "Field_Name");
-    TEST_TRUE(batch, Seg_Field_Name(segment, 3) == NULL,
+    TEST_TRUE(runner, Seg_Field_Name(segment, 3) == NULL,
               "Field_Name returns NULL for unknown field number");
-    TEST_TRUE(batch, Seg_Field_Num(segment, (CharBuf*)bar) == 2,
+    TEST_TRUE(runner, Seg_Field_Num(segment, (CharBuf*)bar) == 2,
               "Field_Num");
-    TEST_TRUE(batch, Seg_Field_Num(segment, (CharBuf*)baz) == 0,
+    TEST_TRUE(runner, Seg_Field_Num(segment, (CharBuf*)baz) == 0,
               "Field_Num returns 0 for unknown field name");
 
     DECREF(segment);
 }
 
 static void
-test_metadata_storage(TestBatch *batch) {
+test_metadata_storage(TestBatchRunner *runner) {
     Segment *segment = Seg_new(1);
     CharBuf *got;
 
     Seg_Store_Metadata_Str(segment, "foo", 3, (Obj*)CB_newf("bar"));
     got = (CharBuf*)Seg_Fetch_Metadata_Str(segment, "foo", 3);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               got
               && CB_Is_A(got, CHARBUF)
               && CB_Equals_Str(got, "bar", 3),
@@ -81,44 +75,44 @@ test_metadata_storage(TestBatch *batch) {
 }
 
 static void
-test_seg_name_and_num(TestBatch *batch) {
+test_seg_name_and_num(TestBatchRunner *runner) {
     Segment *segment_z = Seg_new(35);
     CharBuf *seg_z_name = Seg_num_to_name(35);
-    TEST_TRUE(batch, Seg_Get_Number(segment_z) == INT64_C(35), "Get_Number");
-    TEST_TRUE(batch, CB_Equals_Str(Seg_Get_Name(segment_z), "seg_z", 5),
+    TEST_TRUE(runner, Seg_Get_Number(segment_z) == INT64_C(35), "Get_Number");
+    TEST_TRUE(runner, CB_Equals_Str(Seg_Get_Name(segment_z), "seg_z", 5),
               "Get_Name");
-    TEST_TRUE(batch, CB_Equals_Str(seg_z_name, "seg_z", 5),
+    TEST_TRUE(runner, CB_Equals_Str(seg_z_name, "seg_z", 5),
               "num_to_name");
     DECREF(seg_z_name);
     DECREF(segment_z);
 }
 
 static void
-test_count(TestBatch *batch) {
+test_count(TestBatchRunner *runner) {
     Segment *segment = Seg_new(100);
 
-    TEST_TRUE(batch, Seg_Get_Count(segment) == 0, "count starts off at 0");
+    TEST_TRUE(runner, Seg_Get_Count(segment) == 0, "count starts off at 0");
     Seg_Set_Count(segment, 120);
-    TEST_TRUE(batch, Seg_Get_Count(segment) == 120, "Set_Count");
-    TEST_TRUE(batch, Seg_Increment_Count(segment, 10) == 130,
+    TEST_TRUE(runner, Seg_Get_Count(segment) == 120, "Set_Count");
+    TEST_TRUE(runner, Seg_Increment_Count(segment, 10) == 130,
               "Increment_Count");
 
     DECREF(segment);
 }
 
 static void
-test_Compare_To(TestBatch *batch) {
+test_Compare_To(TestBatchRunner *runner) {
     Segment *segment_1      = Seg_new(1);
     Segment *segment_2      = Seg_new(2);
     Segment *also_segment_2 = Seg_new(2);
 
-    TEST_TRUE(batch, Seg_Compare_To(segment_1, (Obj*)segment_2) < 0,
+    TEST_TRUE(runner, Seg_Compare_To(segment_1, (Obj*)segment_2) < 0,
               "Compare_To 1 < 2");
-    TEST_TRUE(batch, Seg_Compare_To(segment_2, (Obj*)segment_1) > 0,
+    TEST_TRUE(runner, Seg_Compare_To(segment_2, (Obj*)segment_1) > 0,
               "Compare_To 1 < 2");
-    TEST_TRUE(batch, Seg_Compare_To(segment_1, (Obj*)segment_1) == 0,
+    TEST_TRUE(runner, Seg_Compare_To(segment_1, (Obj*)segment_1) == 0,
               "Compare_To identity");
-    TEST_TRUE(batch, Seg_Compare_To(segment_2, (Obj*)also_segment_2) == 0,
+    TEST_TRUE(runner, Seg_Compare_To(segment_2, (Obj*)also_segment_2) == 0,
               "Compare_To 2 == 2");
 
     DECREF(segment_1);
@@ -127,7 +121,7 @@ test_Compare_To(TestBatch *batch) {
 }
 
 static void
-test_Write_File_and_Read_File(TestBatch *batch) {
+test_Write_File_and_Read_File(TestBatchRunner *runner) {
     RAMFolder *folder  = RAMFolder_new(NULL);
     Segment   *segment = Seg_new(100);
     Segment   *got     = Seg_new(100);
@@ -144,13 +138,13 @@ test_Write_File_and_Read_File(TestBatch *batch) {
     Seg_Write_File(segment, (Folder*)folder);
     Seg_Read_File(got, (Folder*)folder);
 
-    TEST_TRUE(batch, Seg_Get_Count(got) == Seg_Get_Count(segment),
+    TEST_TRUE(runner, Seg_Get_Count(got) == Seg_Get_Count(segment),
               "Round-trip count through file");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               Seg_Field_Num(got, jetsam) == Seg_Field_Num(segment, jetsam),
               "Round trip field names through file");
     meta = (CharBuf*)Seg_Fetch_Metadata_Str(got, "foo", 3);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               meta
               && CB_Is_A(meta, CHARBUF)
               && CB_Equals_Str(meta, "bar", 3),
@@ -162,14 +156,14 @@ test_Write_File_and_Read_File(TestBatch *batch) {
 }
 
 void
-TestSeg_run_tests(TestSegment *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_fields(batch);
-    test_metadata_storage(batch);
-    test_seg_name_and_num(batch);
-    test_count(batch);
-    test_Compare_To(batch);
-    test_Write_File_and_Read_File(batch);
+TestSeg_run(TestSegment *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 21);
+    test_fields(runner);
+    test_metadata_storage(runner);
+    test_seg_name_and_num(runner);
+    test_count(runner);
+    test_Compare_To(runner);
+    test_Write_File_and_Read_File(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestSegment.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegment.cfh b/core/Lucy/Test/Index/TestSegment.cfh
index 9af7b60..609a961 100644
--- a/core/Lucy/Test/Index/TestSegment.cfh
+++ b/core/Lucy/Test/Index/TestSegment.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestSegment cnick TestSeg
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSegment*
-    new(TestFormatter *formatter);
-
-    inert TestSegment*
-    init(TestSegment *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSegment *self);
+    Run(TestSegment *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestSnapshot.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSnapshot.c b/core/Lucy/Test/Index/TestSnapshot.c
index 2d204aa..56577fa 100644
--- a/core/Lucy/Test/Index/TestSnapshot.c
+++ b/core/Lucy/Test/Index/TestSnapshot.c
@@ -17,25 +17,19 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestSnapshot.h"
 #include "Lucy/Index/Snapshot.h"
 #include "Lucy/Store/RAMFolder.h"
 
 TestSnapshot*
-TestSnapshot_new(TestFormatter *formatter) {
-    TestSnapshot *self = (TestSnapshot*)VTable_Make_Obj(TESTSNAPSHOT);
-    return TestSnapshot_init(self, formatter);
-}
-
-TestSnapshot*
-TestSnapshot_init(TestSnapshot *self, TestFormatter *formatter) {
-    return (TestSnapshot*)TestBatch_init((TestBatch*)self, 9, formatter);
+TestSnapshot_new() {
+    return (TestSnapshot*)VTable_Make_Obj(TESTSNAPSHOT);
 }
 
 static void
-test_Add_and_Delete(TestBatch *batch) {
+test_Add_and_Delete(TestBatchRunner *runner) {
     Snapshot *snapshot = Snapshot_new();
     CharBuf *foo = (CharBuf*)ZCB_WRAP_STR("foo", 3);
     CharBuf *bar = (CharBuf*)ZCB_WRAP_STR("bar", 3);
@@ -43,38 +37,38 @@ test_Add_and_Delete(TestBatch *batch) {
     Snapshot_Add_Entry(snapshot, foo);
     Snapshot_Add_Entry(snapshot, foo); // redundant
     VArray *entries = Snapshot_List(snapshot);
-    TEST_INT_EQ(batch, Snapshot_Num_Entries(snapshot), 1,
+    TEST_INT_EQ(runner, Snapshot_Num_Entries(snapshot), 1,
                 "One entry added");
-    TEST_TRUE(batch, CB_Equals(foo, VA_Fetch(entries, 0)), "correct entry");
+    TEST_TRUE(runner, CB_Equals(foo, VA_Fetch(entries, 0)), "correct entry");
     DECREF(entries);
 
     Snapshot_Add_Entry(snapshot, bar);
-    TEST_INT_EQ(batch, Snapshot_Num_Entries(snapshot), 2,
+    TEST_INT_EQ(runner, Snapshot_Num_Entries(snapshot), 2,
                 "second entry added");
     Snapshot_Delete_Entry(snapshot, foo);
-    TEST_INT_EQ(batch, Snapshot_Num_Entries(snapshot), 1, "Delete_Entry");
+    TEST_INT_EQ(runner, Snapshot_Num_Entries(snapshot), 1, "Delete_Entry");
 
     DECREF(snapshot);
 }
 
 static void
-test_path_handling(TestBatch *batch) {
+test_path_handling(TestBatchRunner *runner) {
     Snapshot *snapshot = Snapshot_new();
     Folder   *folder   = (Folder*)RAMFolder_new(NULL);
     CharBuf  *snap     = (CharBuf*)ZCB_WRAP_STR("snap", 4);
     CharBuf  *crackle  = (CharBuf*)ZCB_WRAP_STR("crackle", 7);
 
     Snapshot_Write_File(snapshot, folder, snap);
-    TEST_TRUE(batch, CB_Equals(snap, (Obj*)Snapshot_Get_Path(snapshot)),
+    TEST_TRUE(runner, CB_Equals(snap, (Obj*)Snapshot_Get_Path(snapshot)),
               "Write_File() sets path as a side effect");
 
     Folder_Rename(folder, snap, crackle);
     Snapshot_Read_File(snapshot, folder, crackle);
-    TEST_TRUE(batch, CB_Equals(crackle, (Obj*)Snapshot_Get_Path(snapshot)),
+    TEST_TRUE(runner, CB_Equals(crackle, (Obj*)Snapshot_Get_Path(snapshot)),
               "Read_File() sets path as a side effect");
 
     Snapshot_Set_Path(snapshot, snap);
-    TEST_TRUE(batch, CB_Equals(snap, (Obj*)Snapshot_Get_Path(snapshot)),
+    TEST_TRUE(runner, CB_Equals(snap, (Obj*)Snapshot_Get_Path(snapshot)),
               "Set_Path()");
 
     DECREF(folder);
@@ -82,7 +76,7 @@ test_path_handling(TestBatch *batch) {
 }
 
 static void
-test_Read_File_and_Write_File(TestBatch *batch) {
+test_Read_File_and_Write_File(TestBatchRunner *runner) {
     Snapshot *snapshot = Snapshot_new();
     Folder   *folder   = (Folder*)RAMFolder_new(NULL);
     CharBuf  *snap     = (CharBuf*)ZCB_WRAP_STR("snap", 4);
@@ -93,11 +87,11 @@ test_Read_File_and_Write_File(TestBatch *batch) {
 
     Snapshot *dupe = Snapshot_new();
     Snapshot *read_retval = Snapshot_Read_File(dupe, folder, snap);
-    TEST_TRUE(batch, dupe == read_retval, "Read_File() returns the object");
+    TEST_TRUE(runner, dupe == read_retval, "Read_File() returns the object");
 
     VArray *orig_list = Snapshot_List(snapshot);
     VArray *dupe_list = Snapshot_List(dupe);
-    TEST_TRUE(batch, VA_Equals(orig_list, (Obj*)dupe_list),
+    TEST_TRUE(runner, VA_Equals(orig_list, (Obj*)dupe_list),
               "Round trip through Write_File() and Read_File()");
 
     DECREF(orig_list);
@@ -108,11 +102,11 @@ test_Read_File_and_Write_File(TestBatch *batch) {
 }
 
 void
-TestSnapshot_run_tests(TestSnapshot *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Add_and_Delete(batch);
-    test_path_handling(batch);
-    test_Read_File_and_Write_File(batch);
+TestSnapshot_run(TestSnapshot *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 9);
+    test_Add_and_Delete(runner);
+    test_path_handling(runner);
+    test_Read_File_and_Write_File(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestSnapshot.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSnapshot.cfh b/core/Lucy/Test/Index/TestSnapshot.cfh
index cb9f316..3016a42 100644
--- a/core/Lucy/Test/Index/TestSnapshot.cfh
+++ b/core/Lucy/Test/Index/TestSnapshot.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestSnapshot
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSnapshot*
-    new(TestFormatter *formatter);
-
-    inert TestSnapshot*
-    init(TestSnapshot *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSnapshot *self);
+    Run(TestSnapshot *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestTermInfo.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestTermInfo.c b/core/Lucy/Test/Index/TestTermInfo.c
index 9872671..bf92990 100644
--- a/core/Lucy/Test/Index/TestTermInfo.c
+++ b/core/Lucy/Test/Index/TestTermInfo.c
@@ -18,24 +18,18 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestTermInfo.h"
 #include "Lucy/Index/TermInfo.h"
 
 TestTermInfo*
-TestTermInfo_new(TestFormatter *formatter) {
-    TestTermInfo *self = (TestTermInfo*)VTable_Make_Obj(TESTTERMINFO);
-    return TestTermInfo_init(self, formatter);
-}
-
-TestTermInfo*
-TestTermInfo_init(TestTermInfo *self, TestFormatter *formatter) {
-    return (TestTermInfo*)TestBatch_init((TestBatch*)self, 11, formatter);
+TestTermInfo_new() {
+    return (TestTermInfo*)VTable_Make_Obj(TESTTERMINFO);
 }
 
 void 
-test_freqfilepos(TestBatch *batch) {
+test_freqfilepos(TestBatchRunner *runner) {
     TermInfo* tinfo = TInfo_new(10);
     TInfo_Set_Post_FilePos(tinfo, 20);
     TInfo_Set_Skip_FilePos(tinfo, 40);
@@ -43,32 +37,32 @@ test_freqfilepos(TestBatch *batch) {
 
     TermInfo* cloned_tinfo = TInfo_Clone(tinfo);
 
-    TEST_FALSE(batch, Lucy_TInfo_Equals(tinfo, (Obj*)cloned_tinfo),"the clone should be a separate C struct");
-    TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(tinfo), 10, "new sets doc_freq correctly" );
-    TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(tinfo), 10, "... doc_freq cloned" );
-    TEST_INT_EQ(batch, TInfo_Get_Post_FilePos(tinfo), 20, "... post_filepos cloned" );
-    TEST_INT_EQ(batch, TInfo_Get_Skip_FilePos(tinfo), 40, "... skip_filepos cloned" );
-    TEST_INT_EQ(batch, TInfo_Get_Lex_FilePos(tinfo),  50, "... lex_filepos cloned" );
+    TEST_FALSE(runner, Lucy_TInfo_Equals(tinfo, (Obj*)cloned_tinfo),"the clone should be a separate C struct");
+    TEST_INT_EQ(runner, TInfo_Get_Doc_Freq(tinfo), 10, "new sets doc_freq correctly" );
+    TEST_INT_EQ(runner, TInfo_Get_Doc_Freq(tinfo), 10, "... doc_freq cloned" );
+    TEST_INT_EQ(runner, TInfo_Get_Post_FilePos(tinfo), 20, "... post_filepos cloned" );
+    TEST_INT_EQ(runner, TInfo_Get_Skip_FilePos(tinfo), 40, "... skip_filepos cloned" );
+    TEST_INT_EQ(runner, TInfo_Get_Lex_FilePos(tinfo),  50, "... lex_filepos cloned" );
 
     TInfo_Set_Doc_Freq(tinfo, 5);
-    TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(tinfo), 5,  "set/get doc_freq" );
-    TEST_INT_EQ(batch, TInfo_Get_Doc_Freq(cloned_tinfo), 10, "setting orig doesn't affect clone" );
+    TEST_INT_EQ(runner, TInfo_Get_Doc_Freq(tinfo), 5,  "set/get doc_freq" );
+    TEST_INT_EQ(runner, TInfo_Get_Doc_Freq(cloned_tinfo), 10, "setting orig doesn't affect clone" );
 
     TInfo_Set_Post_FilePos(tinfo, 15);
-    TEST_INT_EQ(batch, TInfo_Get_Post_FilePos(tinfo), 15, "set/get post_filepos" );
+    TEST_INT_EQ(runner, TInfo_Get_Post_FilePos(tinfo), 15, "set/get post_filepos" );
 
     TInfo_Set_Skip_FilePos(tinfo, 35);
-    TEST_INT_EQ(batch, TInfo_Get_Skip_FilePos(tinfo), 35, "set/get skip_filepos" );
+    TEST_INT_EQ(runner, TInfo_Get_Skip_FilePos(tinfo), 35, "set/get skip_filepos" );
 
     TInfo_Set_Lex_FilePos(tinfo, 45);
-    TEST_INT_EQ(batch, TInfo_Get_Lex_FilePos(tinfo), 45, "set/get lex_filepos" );
+    TEST_INT_EQ(runner, TInfo_Get_Lex_FilePos(tinfo), 45, "set/get lex_filepos" );
 
     DECREF(tinfo);
     DECREF(cloned_tinfo);
 }
 
 void
-TestTermInfo_run_tests(TestTermInfo *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_freqfilepos(batch);
+TestTermInfo_run(TestTermInfo *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 11);
+    test_freqfilepos(runner);
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestTermInfo.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestTermInfo.cfh b/core/Lucy/Test/Index/TestTermInfo.cfh
index 69e9ee9..4a7d5a3 100644
--- a/core/Lucy/Test/Index/TestTermInfo.cfh
+++ b/core/Lucy/Test/Index/TestTermInfo.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestTermInfo
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestTermInfo*
-    new(TestFormatter *formatter);
-
-    inert TestTermInfo*
-    init(TestTermInfo *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestTermInfo *self);
+    Run(TestTermInfo *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Object/TestBitVector.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestBitVector.c b/core/Lucy/Test/Object/TestBitVector.c
index 669ae67..6e87020 100644
--- a/core/Lucy/Test/Object/TestBitVector.c
+++ b/core/Lucy/Test/Object/TestBitVector.c
@@ -18,71 +18,65 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Object/TestBitVector.h"
 
 TestBitVector*
-TestBitVector_new(TestFormatter *formatter) {
-    TestBitVector *self = (TestBitVector*)VTable_Make_Obj(TESTBITVECTOR);
-    return TestBitVector_init(self, formatter);
-}
-
-TestBitVector*
-TestBitVector_init(TestBitVector *self, TestFormatter *formatter) {
-    return (TestBitVector*)TestBatch_init((TestBatch*)self, 1029, formatter);
+TestBitVector_new() {
+    return (TestBitVector*)VTable_Make_Obj(TESTBITVECTOR);
 }
 
 static void
-test_Set_and_Get(TestBatch *batch) {
+test_Set_and_Get(TestBatchRunner *runner) {
     unsigned i, max;
     const uint32_t  three     = 3;
     const uint32_t  seventeen = 17;
     BitVector      *bit_vec   = BitVec_new(8);
 
     BitVec_Set(bit_vec, three);
-    TEST_TRUE(batch, BitVec_Get_Capacity(bit_vec) < seventeen,
+    TEST_TRUE(runner, BitVec_Get_Capacity(bit_vec) < seventeen,
               "set below cap");
     BitVec_Set(bit_vec, seventeen);
-    TEST_TRUE(batch, BitVec_Get_Capacity(bit_vec) > seventeen,
+    TEST_TRUE(runner, BitVec_Get_Capacity(bit_vec) > seventeen,
               "set above cap causes BitVector to grow");
 
     for (i = 0, max = BitVec_Get_Capacity(bit_vec); i < max; i++) {
         if (i == three || i == seventeen) {
-            TEST_TRUE(batch, BitVec_Get(bit_vec, i), "set/get %d", i);
+            TEST_TRUE(runner, BitVec_Get(bit_vec, i), "set/get %d", i);
         }
         else {
-            TEST_FALSE(batch, BitVec_Get(bit_vec, i), "get %d", i);
+            TEST_FALSE(runner, BitVec_Get(bit_vec, i), "get %d", i);
         }
     }
-    TEST_FALSE(batch, BitVec_Get(bit_vec, i), "out of range get");
+    TEST_FALSE(runner, BitVec_Get(bit_vec, i), "out of range get");
 
     DECREF(bit_vec);
 }
 
 static void
-test_Flip(TestBatch *batch) {
+test_Flip(TestBatchRunner *runner) {
     BitVector *bit_vec = BitVec_new(0);
     int i;
 
     for (i = 0; i <= 20; i++) { BitVec_Flip(bit_vec, i); }
     for (i = 0; i <= 20; i++) {
-        TEST_TRUE(batch, BitVec_Get(bit_vec, i), "flip on %d", i);
+        TEST_TRUE(runner, BitVec_Get(bit_vec, i), "flip on %d", i);
     }
-    TEST_FALSE(batch, BitVec_Get(bit_vec, i), "no flip %d", i);
+    TEST_FALSE(runner, BitVec_Get(bit_vec, i), "no flip %d", i);
     for (i = 0; i <= 20; i++) { BitVec_Flip(bit_vec, i); }
     for (i = 0; i <= 20; i++) {
-        TEST_FALSE(batch, BitVec_Get(bit_vec, i), "flip off %d", i);
+        TEST_FALSE(runner, BitVec_Get(bit_vec, i), "flip off %d", i);
     }
-    TEST_FALSE(batch, BitVec_Get(bit_vec, i), "still no flip %d", i);
+    TEST_FALSE(runner, BitVec_Get(bit_vec, i), "still no flip %d", i);
 
     DECREF(bit_vec);
 }
 
 static void
-test_Flip_Block_ascending(TestBatch *batch) {
+test_Flip_Block_ascending(TestBatchRunner *runner) {
     BitVector *bit_vec = BitVec_new(0);
     int i;
 
@@ -92,11 +86,11 @@ test_Flip_Block_ascending(TestBatch *batch) {
 
     for (i = 0; i <= 20; i++) {
         if (i % 2 == 0) {
-            TEST_TRUE(batch, BitVec_Get(bit_vec, i),
+            TEST_TRUE(runner, BitVec_Get(bit_vec, i),
                       "Flip_Block ascending %d", i);
         }
         else {
-            TEST_FALSE(batch, BitVec_Get(bit_vec, i),
+            TEST_FALSE(runner, BitVec_Get(bit_vec, i),
                        "Flip_Block ascending %d", i);
         }
     }
@@ -105,7 +99,7 @@ test_Flip_Block_ascending(TestBatch *batch) {
 }
 
 static void
-test_Flip_Block_descending(TestBatch *batch) {
+test_Flip_Block_descending(TestBatchRunner *runner) {
     BitVector *bit_vec = BitVec_new(0);
     int i;
 
@@ -115,11 +109,11 @@ test_Flip_Block_descending(TestBatch *batch) {
 
     for (i = 0; i <= 20; i++) {
         if (i % 2) {
-            TEST_TRUE(batch, BitVec_Get(bit_vec, i),
+            TEST_TRUE(runner, BitVec_Get(bit_vec, i),
                       "Flip_Block descending %d", i);
         }
         else {
-            TEST_FALSE(batch, BitVec_Get(bit_vec, i),
+            TEST_FALSE(runner, BitVec_Get(bit_vec, i),
                        "Flip_Block descending %d", i);
         }
     }
@@ -128,7 +122,7 @@ test_Flip_Block_descending(TestBatch *batch) {
 }
 
 static void
-test_Flip_Block_bulk(TestBatch *batch) {
+test_Flip_Block_bulk(TestBatchRunner *runner) {
     int32_t offset;
 
     for (offset = 0; offset <= 17; offset++) {
@@ -147,7 +141,7 @@ test_Flip_Block_bulk(TestBatch *batch) {
                     if (BitVec_Get(bit_vec, i)) { break; }
                 }
             }
-            TEST_INT_EQ(batch, i, 18, "Flip_Block(%d, %d)", offset, len);
+            TEST_INT_EQ(runner, i, 18, "Flip_Block(%d, %d)", offset, len);
 
             DECREF(bit_vec);
         }
@@ -155,7 +149,7 @@ test_Flip_Block_bulk(TestBatch *batch) {
 }
 
 static void
-test_Mimic(TestBatch *batch) {
+test_Mimic(TestBatchRunner *runner) {
     int foo;
 
     for (foo = 0; foo <= 17; foo++) {
@@ -172,7 +166,7 @@ test_Mimic(TestBatch *batch) {
             for (i = 0; i <= 17; i++) {
                 if (BitVec_Get(foo_vec, i) && i != bar) { break; }
             }
-            TEST_INT_EQ(batch, i, 18, "Mimic(%d, %d)", foo, bar);
+            TEST_INT_EQ(runner, i, 18, "Mimic(%d, %d)", foo, bar);
 
             DECREF(foo_vec);
             DECREF(bar_vec);
@@ -232,17 +226,17 @@ S_verify_logical_op(BitVector *bit_vec, BitVector *set_1, BitVector *set_2,
 }
 
 static void
-test_Or(TestBatch *batch) {
+test_Or(TestBatchRunner *runner) {
     BitVector *smaller = S_create_set(1);
     BitVector *larger  = S_create_set(2);
     BitVector *set_1   = S_create_set(1);
     BitVector *set_2   = S_create_set(2);
 
     BitVec_Or(smaller, set_2);
-    TEST_INT_EQ(batch, S_verify_logical_op(smaller, set_1, set_2, OP_OR),
+    TEST_INT_EQ(runner, S_verify_logical_op(smaller, set_1, set_2, OP_OR),
                 50, "OR with self smaller than other");
     BitVec_Or(larger, set_1);
-    TEST_INT_EQ(batch, S_verify_logical_op(larger, set_1, set_2, OP_OR),
+    TEST_INT_EQ(runner, S_verify_logical_op(larger, set_1, set_2, OP_OR),
                 50, "OR with other smaller than self");
 
     DECREF(smaller);
@@ -252,17 +246,17 @@ test_Or(TestBatch *batch) {
 }
 
 static void
-test_Xor(TestBatch *batch) {
+test_Xor(TestBatchRunner *runner) {
     BitVector *smaller = S_create_set(1);
     BitVector *larger  = S_create_set(2);
     BitVector *set_1   = S_create_set(1);
     BitVector *set_2   = S_create_set(2);
 
     BitVec_Xor(smaller, set_2);
-    TEST_INT_EQ(batch, S_verify_logical_op(smaller, set_1, set_2, OP_XOR),
+    TEST_INT_EQ(runner, S_verify_logical_op(smaller, set_1, set_2, OP_XOR),
                 50, "XOR with self smaller than other");
     BitVec_Xor(larger, set_1);
-    TEST_INT_EQ(batch, S_verify_logical_op(larger, set_1, set_2, OP_XOR),
+    TEST_INT_EQ(runner, S_verify_logical_op(larger, set_1, set_2, OP_XOR),
                 50, "XOR with other smaller than self");
 
     DECREF(smaller);
@@ -272,17 +266,17 @@ test_Xor(TestBatch *batch) {
 }
 
 static void
-test_And(TestBatch *batch) {
+test_And(TestBatchRunner *runner) {
     BitVector *smaller = S_create_set(1);
     BitVector *larger  = S_create_set(2);
     BitVector *set_1   = S_create_set(1);
     BitVector *set_2   = S_create_set(2);
 
     BitVec_And(smaller, set_2);
-    TEST_INT_EQ(batch, S_verify_logical_op(smaller, set_1, set_2, OP_AND),
+    TEST_INT_EQ(runner, S_verify_logical_op(smaller, set_1, set_2, OP_AND),
                 50, "AND with self smaller than other");
     BitVec_And(larger, set_1);
-    TEST_INT_EQ(batch, S_verify_logical_op(larger, set_1, set_2, OP_AND),
+    TEST_INT_EQ(runner, S_verify_logical_op(larger, set_1, set_2, OP_AND),
                 50, "AND with other smaller than self");
 
     DECREF(smaller);
@@ -292,18 +286,18 @@ test_And(TestBatch *batch) {
 }
 
 static void
-test_And_Not(TestBatch *batch) {
+test_And_Not(TestBatchRunner *runner) {
     BitVector *smaller = S_create_set(1);
     BitVector *larger  = S_create_set(2);
     BitVector *set_1   = S_create_set(1);
     BitVector *set_2   = S_create_set(2);
 
     BitVec_And_Not(smaller, set_2);
-    TEST_INT_EQ(batch,
+    TEST_INT_EQ(runner,
                 S_verify_logical_op(smaller, set_1, set_2, OP_AND_NOT),
                 50, "AND_NOT with self smaller than other");
     BitVec_And_Not(larger, set_1);
-    TEST_INT_EQ(batch,
+    TEST_INT_EQ(runner,
                 S_verify_logical_op(larger, set_2, set_1, OP_AND_NOT),
                 50, "AND_NOT with other smaller than self");
 
@@ -314,7 +308,7 @@ test_And_Not(TestBatch *batch) {
 }
 
 static void
-test_Count(TestBatch *batch) {
+test_Count(TestBatchRunner *runner) {
     int i;
     int shuffled[64];
     BitVector *bit_vec = BitVec_new(64);
@@ -330,29 +324,29 @@ test_Count(TestBatch *batch) {
         BitVec_Set(bit_vec, shuffled[i]);
         if (BitVec_Count(bit_vec) != (uint32_t)(i + 1)) { break; }
     }
-    TEST_INT_EQ(batch, i, 64, "Count() returns the right number of bits");
+    TEST_INT_EQ(runner, i, 64, "Count() returns the right number of bits");
 
     DECREF(bit_vec);
 }
 
 static void
-test_Next_Hit(TestBatch *batch) {
+test_Next_Hit(TestBatchRunner *runner) {
     int i;
 
     for (i = 24; i <= 33; i++) {
         int probe;
         BitVector *bit_vec = BitVec_new(64);
         BitVec_Set(bit_vec, i);
-        TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, 0), i,
+        TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, 0), i,
                     "Next_Hit for 0 is %d", i);
-        TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, 0), i,
+        TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, 0), i,
                     "Next_Hit for 1 is %d", i);
         for (probe = 15; probe <= i; probe++) {
-            TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, probe), i,
+            TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, probe), i,
                         "Next_Hit for %d is %d", probe, i);
         }
         for (probe = i + 1; probe <= i + 9; probe++) {
-            TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, probe), -1,
+            TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, probe), -1,
                         "no Next_Hit for %d when max is %d", probe, i);
         }
         DECREF(bit_vec);
@@ -360,16 +354,16 @@ test_Next_Hit(TestBatch *batch) {
 }
 
 static void
-test_Clear_All(TestBatch *batch) {
+test_Clear_All(TestBatchRunner *runner) {
     BitVector *bit_vec = BitVec_new(64);
     BitVec_Flip_Block(bit_vec, 0, 63);
     BitVec_Clear_All(bit_vec);
-    TEST_INT_EQ(batch, BitVec_Next_Hit(bit_vec, 0), -1, "Clear_All");
+    TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, 0), -1, "Clear_All");
     DECREF(bit_vec);
 }
 
 static void
-test_Clone(TestBatch *batch) {
+test_Clone(TestBatchRunner *runner) {
     int i;
     BitVector *self = BitVec_new(30);
     BitVector *twin;
@@ -383,8 +377,8 @@ test_Clone(TestBatch *batch) {
     for (i = 0; i < 50; i++) {
         if (BitVec_Get(self, i) != BitVec_Get(twin, i)) { break; }
     }
-    TEST_INT_EQ(batch, i, 50, "Clone");
-    TEST_INT_EQ(batch, BitVec_Count(twin), 4, "clone Count");
+    TEST_INT_EQ(runner, i, 50, "Clone");
+    TEST_INT_EQ(runner, BitVec_Count(twin), 4, "clone Count");
 
     DECREF(self);
     DECREF(twin);
@@ -399,7 +393,7 @@ S_compare_u64s(void *context, const void *va, const void *vb) {
 }
 
 static void
-test_To_Array(TestBatch *batch) {
+test_To_Array(TestBatchRunner *runner) {
     uint64_t  *source_ints = TestUtils_random_u64s(NULL, 20, 0, 200);
     BitVector *bit_vec = BitVec_new(0);
     I32Array  *array;
@@ -426,7 +420,7 @@ test_To_Array(TestBatch *batch) {
     for (i = 0; i < num_unique; i++) {
         if (I32Arr_Get(array, i) != (int32_t)source_ints[i]) { break; }
     }
-    TEST_INT_EQ(batch, i, num_unique, "To_Array (%ld == %ld)", i,
+    TEST_INT_EQ(runner, i, num_unique, "To_Array (%ld == %ld)", i,
                 num_unique);
 
     DECREF(array);
@@ -447,23 +441,23 @@ test_off_by_one_error() {
 }
 
 void
-TestBitVector_run_tests(TestBitVector *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Set_and_Get(batch);
-    test_Flip(batch);
-    test_Flip_Block_ascending(batch);
-    test_Flip_Block_descending(batch);
-    test_Flip_Block_bulk(batch);
-    test_Mimic(batch);
-    test_Or(batch);
-    test_Xor(batch);
-    test_And(batch);
-    test_And_Not(batch);
-    test_Count(batch);
-    test_Next_Hit(batch);
-    test_Clear_All(batch);
-    test_Clone(batch);
-    test_To_Array(batch);
+TestBitVector_run(TestBitVector *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1029);
+    test_Set_and_Get(runner);
+    test_Flip(runner);
+    test_Flip_Block_ascending(runner);
+    test_Flip_Block_descending(runner);
+    test_Flip_Block_bulk(runner);
+    test_Mimic(runner);
+    test_Or(runner);
+    test_Xor(runner);
+    test_And(runner);
+    test_And_Not(runner);
+    test_Count(runner);
+    test_Next_Hit(runner);
+    test_Clear_All(runner);
+    test_Clone(runner);
+    test_To_Array(runner);
     test_off_by_one_error();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Object/TestBitVector.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestBitVector.cfh b/core/Lucy/Test/Object/TestBitVector.cfh
index b7f53bc..e38c66d 100644
--- a/core/Lucy/Test/Object/TestBitVector.cfh
+++ b/core/Lucy/Test/Object/TestBitVector.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Object::TestBitVector
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestBitVector*
-    new(TestFormatter *formatter);
-
-    inert TestBitVector*
-    init(TestBitVector *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestBitVector *self);
+    Run(TestBitVector *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Object/TestI32Array.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestI32Array.c b/core/Lucy/Test/Object/TestI32Array.c
index 2b66430..cc704d2 100644
--- a/core/Lucy/Test/Object/TestI32Array.c
+++ b/core/Lucy/Test/Object/TestI32Array.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Object/TestI32Array.h"
 
@@ -26,18 +26,12 @@ static int32_t source_ints[] = { -1, 0, INT32_MIN, INT32_MAX, 1 };
 static size_t num_ints = sizeof(source_ints) / sizeof(int32_t);
 
 TestI32Array*
-TestI32Arr_new(TestFormatter *formatter) {
-    TestI32Array *self = (TestI32Array*)VTable_Make_Obj(TESTI32ARRAY);
-    return TestI32Arr_init(self, formatter);
-}
-
-TestI32Array*
-TestI32Arr_init(TestI32Array *self, TestFormatter *formatter) {
-    return (TestI32Array*)TestBatch_init((TestBatch*)self, 4, formatter);
+TestI32Arr_new() {
+    return (TestI32Array*)VTable_Make_Obj(TESTI32ARRAY);
 }
 
 static void
-test_all(TestBatch *batch) {
+test_all(TestBatchRunner *runner) {
     I32Array *i32_array = I32Arr_new(source_ints, num_ints);
     int32_t  *ints_copy = (int32_t*)malloc(num_ints * sizeof(int32_t));
     I32Array *stolen    = I32Arr_new_steal(ints_copy, num_ints);
@@ -45,9 +39,9 @@ test_all(TestBatch *batch) {
 
     memcpy(ints_copy, source_ints, num_ints * sizeof(int32_t));
 
-    TEST_TRUE(batch, I32Arr_Get_Size(i32_array) == num_ints,
+    TEST_TRUE(runner, I32Arr_Get_Size(i32_array) == num_ints,
               "Get_Size");
-    TEST_TRUE(batch, I32Arr_Get_Size(stolen) == num_ints,
+    TEST_TRUE(runner, I32Arr_Get_Size(stolen) == num_ints,
               "Get_Size for stolen");
 
     for (num_matched = 0; num_matched < num_ints; num_matched++) {
@@ -55,7 +49,7 @@ test_all(TestBatch *batch) {
             break;
         }
     }
-    TEST_INT_EQ(batch, num_matched, num_ints,
+    TEST_INT_EQ(runner, num_matched, num_ints,
                 "Matched all source ints with Get()");
 
     for (num_matched = 0; num_matched < num_ints; num_matched++) {
@@ -63,7 +57,7 @@ test_all(TestBatch *batch) {
             break;
         }
     }
-    TEST_INT_EQ(batch, num_matched, num_ints,
+    TEST_INT_EQ(runner, num_matched, num_ints,
                 "Matched all source ints in stolen I32Array with Get()");
 
     DECREF(i32_array);
@@ -71,9 +65,9 @@ test_all(TestBatch *batch) {
 }
 
 void
-TestI32Arr_run_tests(TestI32Array *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_all(batch);
+TestI32Arr_run(TestI32Array *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+    test_all(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Object/TestI32Array.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestI32Array.cfh b/core/Lucy/Test/Object/TestI32Array.cfh
index 8211d07..c6411aa 100644
--- a/core/Lucy/Test/Object/TestI32Array.cfh
+++ b/core/Lucy/Test/Object/TestI32Array.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Object::TestI32Array cnick TestI32Arr
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestI32Array*
-    new(TestFormatter *formatter);
-
-    inert TestI32Array*
-    init(TestI32Array *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestI32Array *self);
+    Run(TestI32Array *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestBlobType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestBlobType.c b/core/Lucy/Test/Plan/TestBlobType.c
index 45d5fd9..744f4e1 100644
--- a/core/Lucy/Test/Plan/TestBlobType.c
+++ b/core/Lucy/Test/Plan/TestBlobType.c
@@ -18,34 +18,28 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestBlobType.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Plan/BlobType.h"
 
 TestBlobType*
-TestBlobType_new(TestFormatter *formatter) {
-    TestBlobType *self = (TestBlobType*)VTable_Make_Obj(TESTBLOBTYPE);
-    return TestBlobType_init(self, formatter);
-}
-
-TestBlobType*
-TestBlobType_init(TestBlobType *self, TestFormatter *formatter) {
-    return (TestBlobType*)TestBatch_init((TestBatch*)self, 2, formatter);
+TestBlobType_new() {
+    return (TestBlobType*)VTable_Make_Obj(TESTBLOBTYPE);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     BlobType *type            = BlobType_new(true);
     Obj      *dump            = (Obj*)BlobType_Dump(type);
     Obj      *clone           = Obj_Load(dump, dump);
     Obj      *another_dump    = (Obj*)BlobType_Dump_For_Schema(type);
     BlobType *another_clone   = BlobType_Load(type, another_dump);
 
-    TEST_TRUE(batch, BlobType_Equals(type, (Obj*)clone),
+    TEST_TRUE(runner, BlobType_Equals(type, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_TRUE(batch, BlobType_Equals(type, (Obj*)another_clone),
+    TEST_TRUE(runner, BlobType_Equals(type, (Obj*)another_clone),
               "Dump_For_Schema => Load round trip");
 
     DECREF(type);
@@ -56,9 +50,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestBlobType_run_tests(TestBlobType *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestBlobType_run(TestBlobType *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 2);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestBlobType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestBlobType.cfh b/core/Lucy/Test/Plan/TestBlobType.cfh
index ade91fe..a0ffc79 100644
--- a/core/Lucy/Test/Plan/TestBlobType.cfh
+++ b/core/Lucy/Test/Plan/TestBlobType.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestBlobType
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestBlobType*
-    new(TestFormatter *formatter);
-
-    inert TestBlobType*
-    init(TestBlobType *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestBlobType *self);
+    Run(TestBlobType *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestFieldMisc.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldMisc.c b/core/Lucy/Test/Plan/TestFieldMisc.c
index a4bbf99..d69e622 100644
--- a/core/Lucy/Test/Plan/TestFieldMisc.c
+++ b/core/Lucy/Test/Plan/TestFieldMisc.c
@@ -17,7 +17,7 @@
 
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestFieldMisc.h"
 
@@ -44,14 +44,8 @@ static CharBuf *unindexed_unanalyzed_cb;
 static CharBuf *united_states_cb;
 
 TestFieldMisc*
-TestFieldMisc_new(TestFormatter *formatter) {
-    TestFieldMisc *self = (TestFieldMisc*)VTable_Make_Obj(TESTFIELDMISC);
-    return TestFieldMisc_init(self, formatter);
-}
-
-TestFieldMisc*
-TestFieldMisc_init(TestFieldMisc *self, TestFormatter *formatter) {
-    return (TestFieldMisc*)TestBatch_init((TestBatch*)self, 20, formatter);
+TestFieldMisc_new() {
+    return (TestFieldMisc*)VTable_Make_Obj(TESTFIELDMISC);
 }
 
 static void
@@ -127,13 +121,13 @@ S_add_doc(Indexer *indexer, CharBuf *field_name) {
 }
 
 static void
-S_check(TestBatch *batch, RAMFolder *folder, CharBuf *field,
+S_check(TestBatchRunner *runner, RAMFolder *folder, CharBuf *field,
         CharBuf *query_text, uint32_t expected_num_hits) {
     TermQuery *query = TermQuery_new(field, (Obj*)query_text);
     IndexSearcher *searcher = IxSearcher_new((Obj*)folder);
     Hits *hits = IxSearcher_Hits(searcher, (Obj*)query, 0, 10, NULL);
 
-    TEST_TRUE(batch, Hits_Total_Hits(hits) == expected_num_hits,
+    TEST_TRUE(runner, Hits_Total_Hits(hits) == expected_num_hits,
               "%s correct num hits", CB_Get_Ptr8(field));
 
     // Don't check the contents of the hit if there aren't any.
@@ -141,7 +135,7 @@ S_check(TestBatch *batch, RAMFolder *folder, CharBuf *field,
         HitDoc *hit = Hits_Next(hits);
         ViewCharBuf *value = (ViewCharBuf*)ZCB_BLANK();
         HitDoc_Extract(hit, field, value);
-        TEST_TRUE(batch, CB_Equals(united_states_cb, (Obj*)value),
+        TEST_TRUE(runner, CB_Equals(united_states_cb, (Obj*)value),
                   "%s correct doc returned", CB_Get_Ptr8(field));
         DECREF(hit);
     }
@@ -152,7 +146,7 @@ S_check(TestBatch *batch, RAMFolder *folder, CharBuf *field,
 }
 
 static void
-test_spec_field(TestBatch *batch) {
+test_spec_field(TestBatchRunner *runner) {
     RAMFolder *folder  = RAMFolder_new(NULL);
     Schema    *schema  = S_create_schema();
     Indexer   *indexer = Indexer_new(schema, (Obj*)folder, NULL, 0);
@@ -165,13 +159,13 @@ test_spec_field(TestBatch *batch) {
 
     Indexer_Commit(indexer);
 
-    S_check(batch, folder, analyzed_cb,               states_cb,        1);
-    S_check(batch, folder, easy_analyzed_cb,          state_cb,         1);
-    S_check(batch, folder, string_cb,                 united_states_cb, 1);
-    S_check(batch, folder, unindexed_but_analyzed_cb, state_cb,         0);
-    S_check(batch, folder, unindexed_but_analyzed_cb, united_states_cb, 0);
-    S_check(batch, folder, unindexed_unanalyzed_cb,   state_cb,         0);
-    S_check(batch, folder, unindexed_unanalyzed_cb,   united_states_cb, 0);
+    S_check(runner, folder, analyzed_cb,               states_cb,        1);
+    S_check(runner, folder, easy_analyzed_cb,          state_cb,         1);
+    S_check(runner, folder, string_cb,                 united_states_cb, 1);
+    S_check(runner, folder, unindexed_but_analyzed_cb, state_cb,         0);
+    S_check(runner, folder, unindexed_but_analyzed_cb, united_states_cb, 0);
+    S_check(runner, folder, unindexed_unanalyzed_cb,   state_cb,         0);
+    S_check(runner, folder, unindexed_unanalyzed_cb,   united_states_cb, 0);
 
     DECREF(indexer);
     DECREF(schema);
@@ -191,7 +185,7 @@ S_add_many_fields_doc(Indexer *indexer, CharBuf *content, int num_fields) {
 }
 
 static void
-test_many_fields(TestBatch *batch) {
+test_many_fields(TestBatchRunner *runner) {
     Schema            *schema    = Schema_new();
     StandardTokenizer *tokenizer = StandardTokenizer_new();
     FullTextType      *type      = FullTextType_new((Analyzer*)tokenizer);
@@ -223,7 +217,7 @@ test_many_fields(TestBatch *batch) {
         // See if our search results match as expected.
         IndexSearcher *searcher = IxSearcher_new((Obj*)folder);
         Hits *hits = IxSearcher_Hits(searcher, (Obj*)query, 0, 100, NULL);
-        TEST_TRUE(batch, Hits_Total_Hits(hits) == 2,
+        TEST_TRUE(runner, Hits_Total_Hits(hits) == 2,
                   "correct number of hits for %d fields", num_fields);
         HitDoc *top_hit = Hits_Next(hits);
 
@@ -242,11 +236,11 @@ test_many_fields(TestBatch *batch) {
 }
 
 void
-TestFieldMisc_run_tests(TestFieldMisc *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestFieldMisc_run(TestFieldMisc *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 20);
     S_init_strings();
-    test_spec_field(batch);
-    test_many_fields(batch);
+    test_spec_field(runner);
+    test_many_fields(runner);
     S_destroy_strings();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestFieldMisc.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldMisc.cfh b/core/Lucy/Test/Plan/TestFieldMisc.cfh
index 7673b5d..f3f686a 100644
--- a/core/Lucy/Test/Plan/TestFieldMisc.cfh
+++ b/core/Lucy/Test/Plan/TestFieldMisc.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestFieldMisc
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFieldMisc*
-    new(TestFormatter *formatter);
-
-    inert TestFieldMisc*
-    init(TestFieldMisc *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFieldMisc *self);
+    Run(TestFieldMisc *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestFieldType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldType.c b/core/Lucy/Test/Plan/TestFieldType.c
index 7979aca..1e6c270 100644
--- a/core/Lucy/Test/Plan/TestFieldType.c
+++ b/core/Lucy/Test/Plan/TestFieldType.c
@@ -19,20 +19,14 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestFieldType.h"
 #include "Lucy/Test/TestUtils.h"
 
 TestFieldType*
-TestFType_new(TestFormatter *formatter) {
-    TestFieldType *self = (TestFieldType*)VTable_Make_Obj(TESTFIELDTYPE);
-    return TestFType_init(self, formatter);
-}
-
-TestFieldType*
-TestFType_init(TestFieldType *self, TestFormatter *formatter) {
-    return (TestFieldType*)TestBatch_init((TestBatch*)self, 9, formatter);
+TestFType_new() {
+    return (TestFieldType*)VTable_Make_Obj(TESTFIELDTYPE);
 }
 
 DummyFieldType*
@@ -50,7 +44,7 @@ S_alt_field_type() {
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     FieldType   *type          = (FieldType*)DummyFieldType_new();
     FieldType   *other         = (FieldType*)DummyFieldType_new();
     FieldType   *class_differs = S_alt_field_type();
@@ -66,17 +60,17 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     FType_Set_Indexed(indexed, true);
     FType_Set_Stored(stored, true);
 
-    TEST_TRUE(batch, FType_Equals(type, (Obj*)other),
+    TEST_TRUE(runner, FType_Equals(type, (Obj*)other),
               "Equals() true with identical stats");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)class_differs),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)class_differs),
                "Equals() false with subclass");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)class_differs),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)class_differs),
                "Equals() false with super class");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)boost_differs),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)boost_differs),
                "Equals() false with different boost");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)indexed),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)indexed),
                "Equals() false with indexed => true");
-    TEST_FALSE(batch, FType_Equals(type, (Obj*)stored),
+    TEST_FALSE(runner, FType_Equals(type, (Obj*)stored),
                "Equals() false with stored => true");
 
     DECREF(stored);
@@ -87,18 +81,18 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 static void
-test_Compare_Values(TestBatch *batch) {
+test_Compare_Values(TestBatchRunner *runner) {
     FieldType     *type = (FieldType*)DummyFieldType_new();
     ZombieCharBuf *a    = ZCB_WRAP_STR("a", 1);
     ZombieCharBuf *b    = ZCB_WRAP_STR("b", 1);
 
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FType_Compare_Values(type, (Obj*)a, (Obj*)b) < 0,
               "a less than b");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FType_Compare_Values(type, (Obj*)b, (Obj*)a) > 0,
               "b greater than a");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FType_Compare_Values(type, (Obj*)b, (Obj*)b) == 0,
               "b equals b");
 
@@ -106,10 +100,10 @@ test_Compare_Values(TestBatch *batch) {
 }
 
 void
-TestFType_run_tests(TestFieldType *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
-    test_Compare_Values(batch);
+TestFType_run(TestFieldType *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 9);
+    test_Dump_Load_and_Equals(runner);
+    test_Compare_Values(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestFieldType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldType.cfh b/core/Lucy/Test/Plan/TestFieldType.cfh
index 2632b6f..473e5a0 100644
--- a/core/Lucy/Test/Plan/TestFieldType.cfh
+++ b/core/Lucy/Test/Plan/TestFieldType.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestFieldType cnick TestFType
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFieldType*
-    new(TestFormatter *formatter);
-
-    inert TestFieldType*
-    init(TestFieldType *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFieldType *self);
+    Run(TestFieldType *self, TestBatchRunner *runner);
 }
 
 class Lucy::Test::Plan::DummyFieldType inherits Lucy::Plan::FieldType {

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestFullTextType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFullTextType.c b/core/Lucy/Test/Plan/TestFullTextType.c
index 9ad706b..e47468e 100644
--- a/core/Lucy/Test/Plan/TestFullTextType.c
+++ b/core/Lucy/Test/Plan/TestFullTextType.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestFullTextType.h"
 #include "Lucy/Test/TestUtils.h"
@@ -27,18 +27,12 @@
 #include "Lucy/Analysis/StandardTokenizer.h"
 
 TestFullTextType*
-TestFullTextType_new(TestFormatter *formatter) {
-    TestFullTextType *self = (TestFullTextType*)VTable_Make_Obj(TESTFULLTEXTTYPE);
-    return TestFullTextType_init(self, formatter);
-}
-
-TestFullTextType*
-TestFullTextType_init(TestFullTextType *self, TestFormatter *formatter) {
-    return (TestFullTextType*)TestBatch_init((TestBatch*)self, 10, formatter);
+TestFullTextType_new() {
+    return (TestFullTextType*)VTable_Make_Obj(TESTFULLTEXTTYPE);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     StandardTokenizer *tokenizer     = StandardTokenizer_new();
     Normalizer        *normalizer    = Normalizer_new(NULL, true, false);
     FullTextType      *type          = FullTextType_new((Analyzer*)tokenizer);
@@ -60,19 +54,19 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     Hash_Store_Str((Hash*)another_dump, "analyzer", 8, INCREF(tokenizer));
     FullTextType *another_clone = FullTextType_Load(type, another_dump);
 
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)boost_differs),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)boost_differs),
                "Equals() false with different boost");
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)other),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)other),
                "Equals() false with different Analyzer");
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)not_indexed),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)not_indexed),
                "Equals() false with indexed => false");
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)not_stored),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)not_stored),
                "Equals() false with stored => false");
-    TEST_FALSE(batch, FullTextType_Equals(type, (Obj*)highlightable),
+    TEST_FALSE(runner, FullTextType_Equals(type, (Obj*)highlightable),
                "Equals() false with highlightable => true");
-    TEST_TRUE(batch, FullTextType_Equals(type, (Obj*)clone),
+    TEST_TRUE(runner, FullTextType_Equals(type, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_TRUE(batch, FullTextType_Equals(type, (Obj*)another_clone),
+    TEST_TRUE(runner, FullTextType_Equals(type, (Obj*)another_clone),
               "Dump_For_Schema => Load round trip");
 
     DECREF(another_clone);
@@ -90,19 +84,19 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 static void
-test_Compare_Values(TestBatch *batch) {
+test_Compare_Values(TestBatchRunner *runner) {
     StandardTokenizer *tokenizer = StandardTokenizer_new();
     FullTextType      *type      = FullTextType_new((Analyzer*)tokenizer);
     ZombieCharBuf     *a         = ZCB_WRAP_STR("a", 1);
     ZombieCharBuf     *b         = ZCB_WRAP_STR("b", 1);
 
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FullTextType_Compare_Values(type, (Obj*)a, (Obj*)b) < 0,
               "a less than b");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FullTextType_Compare_Values(type, (Obj*)b, (Obj*)a) > 0,
               "b greater than a");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               FullTextType_Compare_Values(type, (Obj*)b, (Obj*)b) == 0,
               "b equals b");
 
@@ -111,10 +105,10 @@ test_Compare_Values(TestBatch *batch) {
 }
 
 void
-TestFullTextType_run_tests(TestFullTextType *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
-    test_Compare_Values(batch);
+TestFullTextType_run(TestFullTextType *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 10);
+    test_Dump_Load_and_Equals(runner);
+    test_Compare_Values(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestFullTextType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFullTextType.cfh b/core/Lucy/Test/Plan/TestFullTextType.cfh
index 47b9592..cfdbf7c 100644
--- a/core/Lucy/Test/Plan/TestFullTextType.cfh
+++ b/core/Lucy/Test/Plan/TestFullTextType.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestFullTextType
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFullTextType*
-    new(TestFormatter *formatter);
-
-    inert TestFullTextType*
-    init(TestFullTextType *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFullTextType *self);
+    Run(TestFullTextType *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestNumericType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestNumericType.c b/core/Lucy/Test/Plan/TestNumericType.c
index 48ef96c..354f796 100644
--- a/core/Lucy/Test/Plan/TestNumericType.c
+++ b/core/Lucy/Test/Plan/TestNumericType.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestNumericType.h"
 #include "Lucy/Test/TestUtils.h"
@@ -26,47 +26,41 @@
 #include "Lucy/Plan/NumericType.h"
 
 TestNumericType*
-TestNumericType_new(TestFormatter *formatter) {
-    TestNumericType *self = (TestNumericType*)VTable_Make_Obj(TESTNUMERICTYPE);
-    return TestNumericType_init(self, formatter);
-}
-
-TestNumericType*
-TestNumericType_init(TestNumericType *self, TestFormatter *formatter) {
-    return (TestNumericType*)TestBatch_init((TestBatch*)self, 12, formatter);
+TestNumericType_new() {
+    return (TestNumericType*)VTable_Make_Obj(TESTNUMERICTYPE);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     Int32Type   *i32 = Int32Type_new();
     Int64Type   *i64 = Int64Type_new();
     Float32Type *f32 = Float32Type_new();
     Float64Type *f64 = Float64Type_new();
 
-    TEST_FALSE(batch, Int32Type_Equals(i32, (Obj*)i64),
+    TEST_FALSE(runner, Int32Type_Equals(i32, (Obj*)i64),
                "Int32Type_Equals() false for different type");
-    TEST_FALSE(batch, Int32Type_Equals(i32, NULL),
+    TEST_FALSE(runner, Int32Type_Equals(i32, NULL),
                "Int32Type_Equals() false for NULL");
 
-    TEST_FALSE(batch, Int64Type_Equals(i64, (Obj*)i32),
+    TEST_FALSE(runner, Int64Type_Equals(i64, (Obj*)i32),
                "Int64Type_Equals() false for different type");
-    TEST_FALSE(batch, Int64Type_Equals(i64, NULL),
+    TEST_FALSE(runner, Int64Type_Equals(i64, NULL),
                "Int64Type_Equals() false for NULL");
 
-    TEST_FALSE(batch, Float32Type_Equals(f32, (Obj*)f64),
+    TEST_FALSE(runner, Float32Type_Equals(f32, (Obj*)f64),
                "Float32Type_Equals() false for different type");
-    TEST_FALSE(batch, Float32Type_Equals(f32, NULL),
+    TEST_FALSE(runner, Float32Type_Equals(f32, NULL),
                "Float32Type_Equals() false for NULL");
 
-    TEST_FALSE(batch, Float64Type_Equals(f64, (Obj*)f32),
+    TEST_FALSE(runner, Float64Type_Equals(f64, (Obj*)f32),
                "Float64Type_Equals() false for different type");
-    TEST_FALSE(batch, Float64Type_Equals(f64, NULL),
+    TEST_FALSE(runner, Float64Type_Equals(f64, NULL),
                "Float64Type_Equals() false for NULL");
 
     {
         Obj *dump = (Obj*)Int32Type_Dump(i32);
         Obj *other = Obj_Load(dump, dump);
-        TEST_TRUE(batch, Int32Type_Equals(i32, other),
+        TEST_TRUE(runner, Int32Type_Equals(i32, other),
                   "Dump => Load round trip for Int32Type");
         DECREF(dump);
         DECREF(other);
@@ -75,7 +69,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     {
         Obj *dump = (Obj*)Int64Type_Dump(i64);
         Obj *other = Obj_Load(dump, dump);
-        TEST_TRUE(batch, Int64Type_Equals(i64, other),
+        TEST_TRUE(runner, Int64Type_Equals(i64, other),
                   "Dump => Load round trip for Int64Type");
         DECREF(dump);
         DECREF(other);
@@ -84,7 +78,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     {
         Obj *dump = (Obj*)Float32Type_Dump(f32);
         Obj *other = Obj_Load(dump, dump);
-        TEST_TRUE(batch, Float32Type_Equals(f32, other),
+        TEST_TRUE(runner, Float32Type_Equals(f32, other),
                   "Dump => Load round trip for Float32Type");
         DECREF(dump);
         DECREF(other);
@@ -93,7 +87,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     {
         Obj *dump = (Obj*)Float64Type_Dump(f64);
         Obj *other = Obj_Load(dump, dump);
-        TEST_TRUE(batch, Float64Type_Equals(f64, other),
+        TEST_TRUE(runner, Float64Type_Equals(f64, other),
                   "Dump => Load round trip for Float64Type");
         DECREF(dump);
         DECREF(other);
@@ -106,9 +100,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestNumericType_run_tests(TestNumericType *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestNumericType_run(TestNumericType *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 12);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Plan/TestNumericType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestNumericType.cfh b/core/Lucy/Test/Plan/TestNumericType.cfh
index 21c4b31..e3d952e 100644
--- a/core/Lucy/Test/Plan/TestNumericType.cfh
+++ b/core/Lucy/Test/Plan/TestNumericType.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Plan::TestNumericType
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNumericType*
-    new(TestFormatter *formatter);
-
-    inert TestNumericType*
-    init(TestNumericType *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestNumericType *self);
+    Run(TestNumericType *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestLeafQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestLeafQuery.c b/core/Lucy/Test/Search/TestLeafQuery.c
index ba7db58..0fe2b61 100644
--- a/core/Lucy/Test/Search/TestLeafQuery.c
+++ b/core/Lucy/Test/Search/TestLeafQuery.c
@@ -19,25 +19,19 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestLeafQuery.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Search/LeafQuery.h"
 
 TestLeafQuery*
-TestLeafQuery_new(TestFormatter *formatter) {
-    TestLeafQuery *self = (TestLeafQuery*)VTable_Make_Obj(TESTLEAFQUERY);
-    return TestLeafQuery_init(self, formatter);
-}
-
-TestLeafQuery*
-TestLeafQuery_init(TestLeafQuery *self, TestFormatter *formatter) {
-    return (TestLeafQuery*)TestBatch_init((TestBatch*)self, 5, formatter);
+TestLeafQuery_new() {
+    return (TestLeafQuery*)VTable_Make_Obj(TESTLEAFQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     LeafQuery *query         = TestUtils_make_leaf_query("content", "foo");
     LeafQuery *field_differs = TestUtils_make_leaf_query("stuff", "foo");
     LeafQuery *null_field    = TestUtils_make_leaf_query(NULL, "foo");
@@ -46,16 +40,16 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     Obj       *dump          = (Obj*)LeafQuery_Dump(query);
     LeafQuery *clone         = (LeafQuery*)LeafQuery_Load(term_differs, dump);
 
-    TEST_FALSE(batch, LeafQuery_Equals(query, (Obj*)field_differs),
+    TEST_FALSE(runner, LeafQuery_Equals(query, (Obj*)field_differs),
                "Equals() false with different field");
-    TEST_FALSE(batch, LeafQuery_Equals(query, (Obj*)null_field),
+    TEST_FALSE(runner, LeafQuery_Equals(query, (Obj*)null_field),
                "Equals() false with null field");
-    TEST_FALSE(batch, LeafQuery_Equals(query, (Obj*)term_differs),
+    TEST_FALSE(runner, LeafQuery_Equals(query, (Obj*)term_differs),
                "Equals() false with different term");
     LeafQuery_Set_Boost(boost_differs, 0.5);
-    TEST_FALSE(batch, LeafQuery_Equals(query, (Obj*)boost_differs),
+    TEST_FALSE(runner, LeafQuery_Equals(query, (Obj*)boost_differs),
                "Equals() false with different boost");
-    TEST_TRUE(batch, LeafQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, LeafQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
 
     DECREF(query);
@@ -68,9 +62,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestLeafQuery_run_tests(TestLeafQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestLeafQuery_run(TestLeafQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 5);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestLeafQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestLeafQuery.cfh b/core/Lucy/Test/Search/TestLeafQuery.cfh
index 19a9da3..3750b6e 100644
--- a/core/Lucy/Test/Search/TestLeafQuery.cfh
+++ b/core/Lucy/Test/Search/TestLeafQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestLeafQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestLeafQuery*
-    new(TestFormatter *formatter);
-
-    inert TestLeafQuery*
-    init(TestLeafQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestLeafQuery *self);
+    Run(TestLeafQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestMatchAllQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestMatchAllQuery.c b/core/Lucy/Test/Search/TestMatchAllQuery.c
index b70c8f2..4977d6e 100644
--- a/core/Lucy/Test/Search/TestMatchAllQuery.c
+++ b/core/Lucy/Test/Search/TestMatchAllQuery.c
@@ -19,32 +19,26 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestMatchAllQuery.h"
 #include "Lucy/Search/MatchAllQuery.h"
 
 TestMatchAllQuery*
-TestMatchAllQuery_new(TestFormatter *formatter) {
-    TestMatchAllQuery *self = (TestMatchAllQuery*)VTable_Make_Obj(TESTMATCHALLQUERY);
-    return TestMatchAllQuery_init(self, formatter);
-}
-
-TestMatchAllQuery*
-TestMatchAllQuery_init(TestMatchAllQuery *self, TestFormatter *formatter) {
-    return (TestMatchAllQuery*)TestBatch_init((TestBatch*)self, 2, formatter);
+TestMatchAllQuery_new() {
+    return (TestMatchAllQuery*)VTable_Make_Obj(TESTMATCHALLQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     MatchAllQuery *query = MatchAllQuery_new();
     Obj           *dump  = (Obj*)MatchAllQuery_Dump(query);
     MatchAllQuery *clone = (MatchAllQuery*)MatchAllQuery_Load(query, dump);
 
-    TEST_TRUE(batch, MatchAllQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, MatchAllQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_FALSE(batch, MatchAllQuery_Equals(query, (Obj*)CFISH_TRUE),
+    TEST_FALSE(runner, MatchAllQuery_Equals(query, (Obj*)CFISH_TRUE),
                "Equals");
 
     DECREF(query);
@@ -54,9 +48,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 
 
 void
-TestMatchAllQuery_run_tests(TestMatchAllQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestMatchAllQuery_run(TestMatchAllQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 2);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestMatchAllQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestMatchAllQuery.cfh b/core/Lucy/Test/Search/TestMatchAllQuery.cfh
index 1d2a3f5..c4232ff 100644
--- a/core/Lucy/Test/Search/TestMatchAllQuery.cfh
+++ b/core/Lucy/Test/Search/TestMatchAllQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestMatchAllQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestMatchAllQuery*
-    new(TestFormatter *formatter);
-
-    inert TestMatchAllQuery*
-    init(TestMatchAllQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestMatchAllQuery *self);
+    Run(TestMatchAllQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestNOTQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNOTQuery.c b/core/Lucy/Test/Search/TestNOTQuery.c
index c6b7246..ddac353 100644
--- a/core/Lucy/Test/Search/TestNOTQuery.c
+++ b/core/Lucy/Test/Search/TestNOTQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestNOTQuery.h"
@@ -27,18 +27,12 @@
 #include "Lucy/Search/LeafQuery.h"
 
 TestNOTQuery*
-TestNOTQuery_new(TestFormatter *formatter) {
-    TestNOTQuery *self = (TestNOTQuery*)VTable_Make_Obj(TESTNOTQUERY);
-    return TestNOTQuery_init(self, formatter);
-}
-
-TestNOTQuery*
-TestNOTQuery_init(TestNOTQuery *self, TestFormatter *formatter) {
-    return (TestNOTQuery*)TestBatch_init((TestBatch*)self, 4, formatter);
+TestNOTQuery_new() {
+    return (TestNOTQuery*)VTable_Make_Obj(TESTNOTQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     Query    *a_leaf        = (Query*)TestUtils_make_leaf_query(NULL, "a");
     Query    *b_leaf        = (Query*)TestUtils_make_leaf_query(NULL, "b");
     NOTQuery *query         = NOTQuery_new(a_leaf);
@@ -47,14 +41,14 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     Obj      *dump          = (Obj*)NOTQuery_Dump(query);
     NOTQuery *clone         = (NOTQuery*)Obj_Load(dump, dump);
 
-    TEST_FALSE(batch, NOTQuery_Equals(query, (Obj*)kids_differ),
+    TEST_FALSE(runner, NOTQuery_Equals(query, (Obj*)kids_differ),
                "Different kids spoil Equals");
-    TEST_TRUE(batch, NOTQuery_Equals(query, (Obj*)boost_differs),
+    TEST_TRUE(runner, NOTQuery_Equals(query, (Obj*)boost_differs),
               "Equals with identical boosts");
     NOTQuery_Set_Boost(boost_differs, 1.5);
-    TEST_FALSE(batch, NOTQuery_Equals(query, (Obj*)boost_differs),
+    TEST_FALSE(runner, NOTQuery_Equals(query, (Obj*)boost_differs),
                "Different boost spoils Equals");
-    TEST_TRUE(batch, NOTQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, NOTQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
 
     DECREF(a_leaf);
@@ -67,9 +61,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestNOTQuery_run_tests(TestNOTQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestNOTQuery_run(TestNOTQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestNOTQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNOTQuery.cfh b/core/Lucy/Test/Search/TestNOTQuery.cfh
index a2549d3..bc432ff 100644
--- a/core/Lucy/Test/Search/TestNOTQuery.cfh
+++ b/core/Lucy/Test/Search/TestNOTQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestNOTQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNOTQuery*
-    new(TestFormatter *formatter);
-
-    inert TestNOTQuery*
-    init(TestNOTQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestNOTQuery *self);
+    Run(TestNOTQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestNoMatchQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNoMatchQuery.c b/core/Lucy/Test/Search/TestNoMatchQuery.c
index 76a738e..d85c417 100644
--- a/core/Lucy/Test/Search/TestNoMatchQuery.c
+++ b/core/Lucy/Test/Search/TestNoMatchQuery.c
@@ -19,32 +19,26 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestNoMatchQuery.h"
 #include "Lucy/Search/NoMatchQuery.h"
 
 TestNoMatchQuery*
-TestNoMatchQuery_new(TestFormatter *formatter) {
-    TestNoMatchQuery *self = (TestNoMatchQuery*)VTable_Make_Obj(TESTNOMATCHQUERY);
-    return TestNoMatchQuery_init(self, formatter);
-}
-
-TestNoMatchQuery*
-TestNoMatchQuery_init(TestNoMatchQuery *self, TestFormatter *formatter) {
-    return (TestNoMatchQuery*)TestBatch_init((TestBatch*)self, 2, formatter);
+TestNoMatchQuery_new() {
+    return (TestNoMatchQuery*)VTable_Make_Obj(TESTNOMATCHQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     NoMatchQuery *query = NoMatchQuery_new();
     Obj          *dump  = (Obj*)NoMatchQuery_Dump(query);
     NoMatchQuery *clone = (NoMatchQuery*)NoMatchQuery_Load(query, dump);
 
-    TEST_TRUE(batch, NoMatchQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, NoMatchQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_FALSE(batch, NoMatchQuery_Equals(query, (Obj*)CFISH_TRUE),
+    TEST_FALSE(runner, NoMatchQuery_Equals(query, (Obj*)CFISH_TRUE),
                "Equals");
 
     DECREF(query);
@@ -54,9 +48,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 
 
 void
-TestNoMatchQuery_run_tests(TestNoMatchQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestNoMatchQuery_run(TestNoMatchQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 2);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestNoMatchQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNoMatchQuery.cfh b/core/Lucy/Test/Search/TestNoMatchQuery.cfh
index 9b2344d..cb3420e 100644
--- a/core/Lucy/Test/Search/TestNoMatchQuery.cfh
+++ b/core/Lucy/Test/Search/TestNoMatchQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestNoMatchQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNoMatchQuery*
-    new(TestFormatter *formatter);
-
-    inert TestNoMatchQuery*
-    init(TestNoMatchQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestNoMatchQuery *self);
+    Run(TestNoMatchQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestPhraseQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPhraseQuery.c b/core/Lucy/Test/Search/TestPhraseQuery.c
index d350f95..3fe0182 100644
--- a/core/Lucy/Test/Search/TestPhraseQuery.c
+++ b/core/Lucy/Test/Search/TestPhraseQuery.c
@@ -19,30 +19,24 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestPhraseQuery.h"
 #include "Lucy/Search/PhraseQuery.h"
 
 TestPhraseQuery*
-TestPhraseQuery_new(TestFormatter *formatter) {
-    TestPhraseQuery *self = (TestPhraseQuery*)VTable_Make_Obj(TESTPHRASEQUERY);
-    return TestPhraseQuery_init(self, formatter);
-}
-
-TestPhraseQuery*
-TestPhraseQuery_init(TestPhraseQuery *self, TestFormatter *formatter) {
-    return (TestPhraseQuery*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestPhraseQuery_new() {
+    return (TestPhraseQuery*)VTable_Make_Obj(TESTPHRASEQUERY);
 }
 
 static void
-test_Dump_And_Load(TestBatch *batch) {
+test_Dump_And_Load(TestBatchRunner *runner) {
     PhraseQuery *query
         = TestUtils_make_phrase_query("content", "a", "b", "c", NULL);
     Obj         *dump  = (Obj*)PhraseQuery_Dump(query);
     PhraseQuery *twin = (PhraseQuery*)Obj_Load(dump, dump);
-    TEST_TRUE(batch, PhraseQuery_Equals(query, (Obj*)twin),
+    TEST_TRUE(runner, PhraseQuery_Equals(query, (Obj*)twin),
               "Dump => Load round trip");
     DECREF(query);
     DECREF(dump);
@@ -50,9 +44,9 @@ test_Dump_And_Load(TestBatch *batch) {
 }
 
 void
-TestPhraseQuery_run_tests(TestPhraseQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_And_Load(batch);
+TestPhraseQuery_run(TestPhraseQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    test_Dump_And_Load(runner);
 }
 
 


[lucy-commits] [15/26] Move test harness classes to Clownfish::TestHarness

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/TestHarness/TestRunner.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestRunner.c b/core/Clownfish/TestHarness/TestRunner.c
new file mode 100644
index 0000000..3132d39
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestRunner.c
@@ -0,0 +1,93 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define C_CFISH_TESTRUNNER
+#define CFISH_USE_SHORT_NAMES
+#define LUCY_USE_SHORT_NAMES
+#define CHY_USE_SHORT_NAMES
+
+#include "Clownfish/TestHarness/TestRunner.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/VTable.h"
+
+TestRunner*
+TestRunner_new(TestFormatter *formatter) {
+    TestRunner *self = (TestRunner*)VTable_Make_Obj(TESTRUNNER);
+    return TestRunner_init(self, formatter);
+}
+
+TestRunner*
+TestRunner_init(TestRunner *self, TestFormatter *formatter) {
+    self->formatter          = (TestFormatter*)INCREF(formatter);
+    self->num_tests          = 0;
+    self->num_tests_failed   = 0;
+    self->num_batches        = 0;
+    self->num_batches_failed = 0;
+
+    return self;
+}
+
+void
+TestRunner_destroy(TestRunner *self) {
+    DECREF(self->formatter);
+    SUPER_DESTROY(self, TESTRUNNER);
+}
+
+bool
+TestRunner_run_batch(TestRunner *self, TestBatch *batch) {
+    bool success = TestBatch_Run(batch);
+
+    self->num_tests        += TestBatch_Get_Num_Tests(batch);
+    self->num_tests_failed += TestBatch_Get_Num_Failed(batch);
+    self->num_batches      += 1;
+
+    if (!success) {
+        self->num_batches_failed += 1;
+    }
+
+    return success;
+}
+
+bool
+TestRunner_finish(TestRunner *self) {
+    TestFormatter_Summary(self->formatter, self);
+
+    return self->num_batches != 0 && self->num_batches_failed == 0;
+}
+
+uint32_t
+TestRunner_get_num_tests(TestRunner *self) {
+    return self->num_tests;
+}
+
+uint32_t
+TestRunner_get_num_tests_failed(TestRunner *self) {
+    return self->num_tests_failed;
+}
+
+uint32_t
+TestRunner_get_num_batches(TestRunner *self) {
+    return self->num_batches;
+}
+
+uint32_t
+TestRunner_get_num_batches_failed(TestRunner *self) {
+    return self->num_batches_failed;
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/TestHarness/TestRunner.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestRunner.cfh b/core/Clownfish/TestHarness/TestRunner.cfh
new file mode 100644
index 0000000..8bebac0
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestRunner.cfh
@@ -0,0 +1,77 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Clownfish;
+
+/**
+ * Run multiple test batches and collect statistics.
+ */
+class Clownfish::TestHarness::TestRunner inherits Clownfish::Obj {
+    TestFormatter *formatter;
+    uint32_t       num_tests;
+    uint32_t       num_tests_failed;
+    uint32_t       num_batches;
+    uint32_t       num_batches_failed;
+
+    inert incremented TestRunner*
+    new(TestFormatter *formatter);
+
+    /**
+     * @param formatter The test formatter to format the test output.
+     */
+    inert TestRunner*
+    init(TestRunner *self, TestFormatter *formatter);
+
+    public void
+    Destroy(TestRunner *self);
+
+    /** Run a test batch and collect statistics.
+     *
+     * @param batch The test batch.
+     * @return true if the test batch passed.
+     */
+    bool
+    Run_Batch(TestRunner *self, TestBatch *batch);
+
+    /** Print a summary after running all test batches.
+     *
+     * @return true if any tests were run and all test batches passed.
+     */
+    bool
+    Finish(TestRunner *self);
+
+    /** Return the number of tests run.
+     */
+    uint32_t
+    Get_Num_Tests(TestRunner *self);
+
+    /** Return the number of failed tests.
+     */
+    uint32_t
+    Get_Num_Tests_Failed(TestRunner *self);
+
+    /** Return the number of test batches run.
+     */
+    uint32_t
+    Get_Num_Batches(TestRunner *self);
+
+    /** Return the number of failed test batches.
+     */
+    uint32_t
+    Get_Num_Batches_Failed(TestRunner *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/TestHarness/TestUtils.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestUtils.c b/core/Clownfish/TestHarness/TestUtils.c
new file mode 100644
index 0000000..a45bf87
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestUtils.c
@@ -0,0 +1,140 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
+#define LUCY_USE_SHORT_NAMES
+
+#include "Clownfish/TestHarness/TestUtils.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Util/Memory.h"
+#include "Lucy/Store/InStream.h"
+#include "Lucy/Store/OutStream.h"
+#include "Lucy/Store/RAMFile.h"
+#include "Lucy/Util/Freezer.h"
+
+uint64_t
+TestUtils_random_u64() {
+    uint64_t num = ((uint64_t)(rand()   & 0x7FFF) << 60)
+                   | ((uint64_t)(rand() & 0x7FFF) << 45)
+                   | ((uint64_t)(rand() & 0x7FFF) << 30)
+                   | ((uint64_t)(rand() & 0x7FFF) << 15)
+                   | ((uint64_t)(rand() & 0x7FFF) << 0);
+    return num;
+}
+
+int64_t*
+TestUtils_random_i64s(int64_t *buf, size_t count, int64_t min,
+                      int64_t limit) {
+    uint64_t  range = min < limit ? limit - min : 0;
+    int64_t *ints = buf ? buf : (int64_t*)CALLOCATE(count, sizeof(int64_t));
+    for (size_t i = 0; i < count; i++) {
+        ints[i] = min + TestUtils_random_u64() % range;
+    }
+    return ints;
+}
+
+uint64_t*
+TestUtils_random_u64s(uint64_t *buf, size_t count, uint64_t min,
+                      uint64_t limit) {
+    uint64_t  range = min < limit ? limit - min : 0;
+    uint64_t *ints = buf ? buf : (uint64_t*)CALLOCATE(count, sizeof(uint64_t));
+    for (size_t i = 0; i < count; i++) {
+        ints[i] = min + TestUtils_random_u64() % range;
+    }
+    return ints;
+}
+
+double*
+TestUtils_random_f64s(double *buf, size_t count) {
+    double *f64s = buf ? buf : (double*)CALLOCATE(count, sizeof(double));
+    for (size_t i = 0; i < count; i++) {
+        uint64_t num = TestUtils_random_u64();
+        f64s[i] = U64_TO_DOUBLE(num) / UINT64_MAX;
+    }
+    return f64s;
+}
+
+static uint32_t
+S_random_code_point(void) {
+    uint32_t code_point = 0;
+    while (1) {
+        uint8_t chance = (rand() % 9) + 1;
+        switch (chance) {
+            case 1: case 2: case 3:
+                code_point = rand() % 0x80;
+                break;
+            case 4: case 5: case 6:
+                code_point = (rand() % (0x0800  - 0x0080)) + 0x0080;
+                break;
+            case 7: case 8:
+                code_point = (rand() % (0x10000 - 0x0800)) + 0x0800;
+                break;
+            case 9: {
+                    uint64_t num = TestUtils_random_u64();
+                    code_point = (num % (0x10FFFF - 0x10000)) + 0x10000;
+                }
+        }
+        if (code_point > 0x10FFFF) {
+            continue; // Too high.
+        }
+        if (code_point > 0xD7FF && code_point < 0xE000) {
+            continue; // UTF-16 surrogate.
+        }
+        break;
+    }
+    return code_point;
+}
+
+CharBuf*
+TestUtils_random_string(size_t length) {
+    CharBuf *string = CB_new(length);
+    while (length--) {
+        CB_Cat_Char(string, S_random_code_point());
+    }
+    return string;
+}
+
+CharBuf*
+TestUtils_get_cb(const char *ptr) {
+    return CB_new_from_utf8(ptr, strlen(ptr));
+}
+
+Obj*
+TestUtils_freeze_thaw(Obj *object) {
+    if (object) {
+        RAMFile *ram_file = RAMFile_new(NULL, false);
+        OutStream *outstream = OutStream_open((Obj*)ram_file);
+        FREEZE(object, outstream);
+        OutStream_Close(outstream);
+        DECREF(outstream);
+
+        InStream *instream = InStream_open((Obj*)ram_file);
+        Obj *retval = THAW(instream);
+        DECREF(instream);
+        DECREF(ram_file);
+        return retval;
+    }
+    else {
+        return NULL;
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/TestHarness/TestUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestUtils.cfh b/core/Clownfish/TestHarness/TestUtils.cfh
new file mode 100644
index 0000000..507114d
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestUtils.cfh
@@ -0,0 +1,71 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Clownfish;
+
+inert class Clownfish::TestHarness::TestUtils  {
+
+    /** Testing-only CharBuf factory which uses strlen().
+     */
+    inert incremented CharBuf*
+    get_cb(const char *utf8);
+
+    /** Return a random unsigned 64-bit integer.
+     */
+    inert uint64_t
+    random_u64();
+
+    /** Return an array of <code>count</code> random 64-bit integers where
+     * <code>min <= n < limit</code>.
+     *
+     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
+     * be used.
+     */
+    inert int64_t*
+    random_i64s(int64_t *buf, size_t count, int64_t min, int64_t limit);
+
+    /** Return an array of <code>count</code> random unsigned, 64-bit integers
+     * where <code>min <= n < limit</code>.
+     *
+     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
+     * be used.
+     */
+    inert uint64_t*
+    random_u64s(uint64_t *buf, size_t count, uint64_t min, uint64_t limit);
+
+    /** Return an array of <code>count</code> random double-precision floating
+     * point numbers between 0 and 1.
+     *
+     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
+     * be used.
+     */
+    inert double*
+    random_f64s(double *buf, size_t count);
+
+    /** Return a string with a random (legal) sequence of code points.
+     * @param length Length of the string in code points.
+     */
+    inert incremented CharBuf*
+    random_string(size_t length);
+
+    /** Return the result of round-tripping the object through FREEZE and
+     * THAW.
+     */
+    inert incremented Obj*
+    freeze_thaw(Obj *object);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test.c b/core/Lucy/Test.c
index ded5834..c131931 100644
--- a/core/Lucy/Test.c
+++ b/core/Lucy/Test.c
@@ -20,9 +20,9 @@
 #include "Lucy/Util/ToolSet.h"
 
 #include "Lucy/Test.h"
-#include "Clownfish/Test/TestBatch.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/Test/TestRunner.h"
+#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestRunner.h"
 #include "Lucy/Test/Analysis/TestAnalyzer.h"
 #include "Lucy/Test/Analysis/TestCaseFolder.h"
 #include "Lucy/Test/Analysis/TestNormalizer.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestAnalyzer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestAnalyzer.c b/core/Lucy/Test/Analysis/TestAnalyzer.c
index 1443f8c..04e6fc7 100644
--- a/core/Lucy/Test/Analysis/TestAnalyzer.c
+++ b/core/Lucy/Test/Analysis/TestAnalyzer.c
@@ -17,7 +17,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Analysis/TestAnalyzer.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestAnalyzer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestAnalyzer.cfh b/core/Lucy/Test/Analysis/TestAnalyzer.cfh
index 78c0391..e9d67ea 100644
--- a/core/Lucy/Test/Analysis/TestAnalyzer.cfh
+++ b/core/Lucy/Test/Analysis/TestAnalyzer.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Analysis::TestAnalyzer
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestAnalyzer*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestCaseFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestCaseFolder.c b/core/Lucy/Test/Analysis/TestCaseFolder.c
index 8ee0f51..1c8670b 100644
--- a/core/Lucy/Test/Analysis/TestCaseFolder.c
+++ b/core/Lucy/Test/Analysis/TestCaseFolder.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Analysis/TestCaseFolder.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestCaseFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestCaseFolder.cfh b/core/Lucy/Test/Analysis/TestCaseFolder.cfh
index 087a5e1..2ff9067 100644
--- a/core/Lucy/Test/Analysis/TestCaseFolder.cfh
+++ b/core/Lucy/Test/Analysis/TestCaseFolder.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Analysis::TestCaseFolder
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestCaseFolder*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestNormalizer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestNormalizer.c b/core/Lucy/Test/Analysis/TestNormalizer.c
index 94904d2..40d26e3 100644
--- a/core/Lucy/Test/Analysis/TestNormalizer.c
+++ b/core/Lucy/Test/Analysis/TestNormalizer.c
@@ -19,7 +19,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestNormalizer.h"
 #include "Lucy/Analysis/Normalizer.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestNormalizer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestNormalizer.cfh b/core/Lucy/Test/Analysis/TestNormalizer.cfh
index cff80bc..ac5567f 100644
--- a/core/Lucy/Test/Analysis/TestNormalizer.cfh
+++ b/core/Lucy/Test/Analysis/TestNormalizer.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Analysis::TestNormalizer
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNormalizer*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestPolyAnalyzer.c b/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
index a1f3f8f..cee8df1 100644
--- a/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
+++ b/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Analysis/TestPolyAnalyzer.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh b/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
index 2e5319b..7d4d2fc 100644
--- a/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
+++ b/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Analysis::TestPolyAnalyzer
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPolyAnalyzer*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestRegexTokenizer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestRegexTokenizer.c b/core/Lucy/Test/Analysis/TestRegexTokenizer.c
index 92b9b5b..cf9bb72 100644
--- a/core/Lucy/Test/Analysis/TestRegexTokenizer.c
+++ b/core/Lucy/Test/Analysis/TestRegexTokenizer.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestRegexTokenizer.h"
 #include "Lucy/Analysis/RegexTokenizer.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh b/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
index 8a23975..bb0f352 100644
--- a/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
+++ b/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Analysis::TestRegexTokenizer
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRegexTokenizer*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestSnowballStemmer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStemmer.c b/core/Lucy/Test/Analysis/TestSnowballStemmer.c
index f045fe0..36a1879 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStemmer.c
+++ b/core/Lucy/Test/Analysis/TestSnowballStemmer.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestSnowballStemmer.h"
 #include "Lucy/Analysis/SnowballStemmer.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh b/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
index f91aea4..8a651ee 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
+++ b/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Analysis::TestSnowballStemmer cnick TestSnowStemmer
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSnowballStemmer*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStopFilter.c b/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
index 0e5663e..217464a 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
+++ b/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestSnowballStopFilter.h"
 #include "Lucy/Analysis/SnowballStopFilter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh b/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
index c80864b..33140a5 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
+++ b/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Analysis::TestSnowballStopFilter cnick TestSnowStop
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSnowballStopFilter*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestStandardTokenizer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestStandardTokenizer.c b/core/Lucy/Test/Analysis/TestStandardTokenizer.c
index 9f1775c..063e17c 100644
--- a/core/Lucy/Test/Analysis/TestStandardTokenizer.c
+++ b/core/Lucy/Test/Analysis/TestStandardTokenizer.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestStandardTokenizer.h"
 #include "Lucy/Analysis/StandardTokenizer.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh b/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
index 12f93b6..257879d 100644
--- a/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
+++ b/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Analysis::TestStandardTokenizer
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestStandardTokenizer*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Highlight/TestHeatMap.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHeatMap.c b/core/Lucy/Test/Highlight/TestHeatMap.c
index 08877e8..2f2da84 100644
--- a/core/Lucy/Test/Highlight/TestHeatMap.c
+++ b/core/Lucy/Test/Highlight/TestHeatMap.c
@@ -17,7 +17,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Highlight/TestHeatMap.h"
 #include "Lucy/Highlight/HeatMap.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Highlight/TestHeatMap.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHeatMap.cfh b/core/Lucy/Test/Highlight/TestHeatMap.cfh
index 8df87c9..2a4ed5a 100644
--- a/core/Lucy/Test/Highlight/TestHeatMap.cfh
+++ b/core/Lucy/Test/Highlight/TestHeatMap.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Highlight::TestHeatMap
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestHeatMap*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Highlight/TestHighlighter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHighlighter.c b/core/Lucy/Test/Highlight/TestHighlighter.c
index 4194539..808267b 100644
--- a/core/Lucy/Test/Highlight/TestHighlighter.c
+++ b/core/Lucy/Test/Highlight/TestHighlighter.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Highlight/TestHighlighter.h"
 #include "Lucy/Highlight/Highlighter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Highlight/TestHighlighter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHighlighter.cfh b/core/Lucy/Test/Highlight/TestHighlighter.cfh
index 6419bb9..848836d 100644
--- a/core/Lucy/Test/Highlight/TestHighlighter.cfh
+++ b/core/Lucy/Test/Highlight/TestHighlighter.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Highlight::TestHighlighter
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestHighlighter*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestDocWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestDocWriter.c b/core/Lucy/Test/Index/TestDocWriter.c
index b49a30f..879d830 100644
--- a/core/Lucy/Test/Index/TestDocWriter.c
+++ b/core/Lucy/Test/Index/TestDocWriter.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestDocWriter.h"
 #include "Lucy/Index/DocWriter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestDocWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestDocWriter.cfh b/core/Lucy/Test/Index/TestDocWriter.cfh
index 40403af..1426d1c 100644
--- a/core/Lucy/Test/Index/TestDocWriter.cfh
+++ b/core/Lucy/Test/Index/TestDocWriter.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Index::TestDocWriter
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestDocWriter*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestHighlightWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestHighlightWriter.c b/core/Lucy/Test/Index/TestHighlightWriter.c
index e4152f6..791da1b 100644
--- a/core/Lucy/Test/Index/TestHighlightWriter.c
+++ b/core/Lucy/Test/Index/TestHighlightWriter.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestHighlightWriter.h"
 #include "Lucy/Index/HighlightWriter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestHighlightWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestHighlightWriter.cfh b/core/Lucy/Test/Index/TestHighlightWriter.cfh
index 7173c63..d761e38 100644
--- a/core/Lucy/Test/Index/TestHighlightWriter.cfh
+++ b/core/Lucy/Test/Index/TestHighlightWriter.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Index::TestHighlightWriter cnick TestHLWriter
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestHighlightWriter*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestIndexManager.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestIndexManager.c b/core/Lucy/Test/Index/TestIndexManager.c
index aeda532..a856300 100644
--- a/core/Lucy/Test/Index/TestIndexManager.c
+++ b/core/Lucy/Test/Index/TestIndexManager.c
@@ -17,7 +17,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestIndexManager.h"
 #include "Lucy/Index/IndexManager.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestIndexManager.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestIndexManager.cfh b/core/Lucy/Test/Index/TestIndexManager.cfh
index 911afaa..105b833 100644
--- a/core/Lucy/Test/Index/TestIndexManager.cfh
+++ b/core/Lucy/Test/Index/TestIndexManager.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Index::TestIndexManager cnick TestIxManager
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestIndexManager*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestPolyReader.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPolyReader.c b/core/Lucy/Test/Index/TestPolyReader.c
index 58bd248..2f8dfc5 100644
--- a/core/Lucy/Test/Index/TestPolyReader.c
+++ b/core/Lucy/Test/Index/TestPolyReader.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestPolyReader.h"
 #include "Lucy/Index/PolyReader.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestPolyReader.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPolyReader.cfh b/core/Lucy/Test/Index/TestPolyReader.cfh
index 1040439..36c957e 100644
--- a/core/Lucy/Test/Index/TestPolyReader.cfh
+++ b/core/Lucy/Test/Index/TestPolyReader.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Index::TestPolyReader
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPolyReader*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestPostingListWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPostingListWriter.c b/core/Lucy/Test/Index/TestPostingListWriter.c
index 27db6a8..f393665 100644
--- a/core/Lucy/Test/Index/TestPostingListWriter.c
+++ b/core/Lucy/Test/Index/TestPostingListWriter.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestPostingListWriter.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestPostingListWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPostingListWriter.cfh b/core/Lucy/Test/Index/TestPostingListWriter.cfh
index 353bdbe..5c460bf 100644
--- a/core/Lucy/Test/Index/TestPostingListWriter.cfh
+++ b/core/Lucy/Test/Index/TestPostingListWriter.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Index::TestPostingListWriter cnick TestPListWriter
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPostingListWriter*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestSegWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegWriter.c b/core/Lucy/Test/Index/TestSegWriter.c
index e949c9d..1e26311 100644
--- a/core/Lucy/Test/Index/TestSegWriter.c
+++ b/core/Lucy/Test/Index/TestSegWriter.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestSegWriter.h"
 #include "Lucy/Index/SegWriter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestSegWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegWriter.cfh b/core/Lucy/Test/Index/TestSegWriter.cfh
index 471df86..1ca9eaa 100644
--- a/core/Lucy/Test/Index/TestSegWriter.cfh
+++ b/core/Lucy/Test/Index/TestSegWriter.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Index::TestSegWriter
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSegWriter*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestSegment.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegment.c b/core/Lucy/Test/Index/TestSegment.c
index aa46dac..f0a3596 100644
--- a/core/Lucy/Test/Index/TestSegment.c
+++ b/core/Lucy/Test/Index/TestSegment.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestSegment.h"
 #include "Lucy/Index/Segment.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestSegment.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegment.cfh b/core/Lucy/Test/Index/TestSegment.cfh
index 76feab5..9af7b60 100644
--- a/core/Lucy/Test/Index/TestSegment.cfh
+++ b/core/Lucy/Test/Index/TestSegment.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Index::TestSegment cnick TestSeg
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSegment*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestSnapshot.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSnapshot.c b/core/Lucy/Test/Index/TestSnapshot.c
index 3e905cb..2d204aa 100644
--- a/core/Lucy/Test/Index/TestSnapshot.c
+++ b/core/Lucy/Test/Index/TestSnapshot.c
@@ -17,7 +17,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestSnapshot.h"
 #include "Lucy/Index/Snapshot.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestSnapshot.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSnapshot.cfh b/core/Lucy/Test/Index/TestSnapshot.cfh
index 4ecdf9d..cb9f316 100644
--- a/core/Lucy/Test/Index/TestSnapshot.cfh
+++ b/core/Lucy/Test/Index/TestSnapshot.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Index::TestSnapshot
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSnapshot*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestTermInfo.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestTermInfo.c b/core/Lucy/Test/Index/TestTermInfo.c
index 3474e56..9872671 100644
--- a/core/Lucy/Test/Index/TestTermInfo.c
+++ b/core/Lucy/Test/Index/TestTermInfo.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestTermInfo.h"
 #include "Lucy/Index/TermInfo.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Index/TestTermInfo.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestTermInfo.cfh b/core/Lucy/Test/Index/TestTermInfo.cfh
index 6f7cb43..69e9ee9 100644
--- a/core/Lucy/Test/Index/TestTermInfo.cfh
+++ b/core/Lucy/Test/Index/TestTermInfo.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Index::TestTermInfo
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestTermInfo*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Object/TestBitVector.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestBitVector.c b/core/Lucy/Test/Object/TestBitVector.c
index cce4df9..cd04fbb 100644
--- a/core/Lucy/Test/Object/TestBitVector.c
+++ b/core/Lucy/Test/Object/TestBitVector.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Object/TestBitVector.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Object/TestBitVector.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestBitVector.cfh b/core/Lucy/Test/Object/TestBitVector.cfh
index 75a1006..b7f53bc 100644
--- a/core/Lucy/Test/Object/TestBitVector.cfh
+++ b/core/Lucy/Test/Object/TestBitVector.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Object::TestBitVector
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestBitVector*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Object/TestI32Array.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestI32Array.c b/core/Lucy/Test/Object/TestI32Array.c
index 058d9ec..2b66430 100644
--- a/core/Lucy/Test/Object/TestI32Array.c
+++ b/core/Lucy/Test/Object/TestI32Array.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Object/TestI32Array.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Object/TestI32Array.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestI32Array.cfh b/core/Lucy/Test/Object/TestI32Array.cfh
index 7f5c19f..8211d07 100644
--- a/core/Lucy/Test/Object/TestI32Array.cfh
+++ b/core/Lucy/Test/Object/TestI32Array.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Object::TestI32Array cnick TestI32Arr
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestI32Array*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestBlobType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestBlobType.c b/core/Lucy/Test/Plan/TestBlobType.c
index 2012088..45d5fd9 100644
--- a/core/Lucy/Test/Plan/TestBlobType.c
+++ b/core/Lucy/Test/Plan/TestBlobType.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestBlobType.h"
 #include "Lucy/Test/TestUtils.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestBlobType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestBlobType.cfh b/core/Lucy/Test/Plan/TestBlobType.cfh
index 8ec6fc1..ade91fe 100644
--- a/core/Lucy/Test/Plan/TestBlobType.cfh
+++ b/core/Lucy/Test/Plan/TestBlobType.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Plan::TestBlobType
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestBlobType*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestFieldMisc.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldMisc.c b/core/Lucy/Test/Plan/TestFieldMisc.c
index bd39cc4..a4bbf99 100644
--- a/core/Lucy/Test/Plan/TestFieldMisc.c
+++ b/core/Lucy/Test/Plan/TestFieldMisc.c
@@ -17,7 +17,7 @@
 
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestFieldMisc.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestFieldMisc.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldMisc.cfh b/core/Lucy/Test/Plan/TestFieldMisc.cfh
index 98734b8..7673b5d 100644
--- a/core/Lucy/Test/Plan/TestFieldMisc.cfh
+++ b/core/Lucy/Test/Plan/TestFieldMisc.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Plan::TestFieldMisc
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFieldMisc*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestFieldType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldType.c b/core/Lucy/Test/Plan/TestFieldType.c
index e2ce6b2..7979aca 100644
--- a/core/Lucy/Test/Plan/TestFieldType.c
+++ b/core/Lucy/Test/Plan/TestFieldType.c
@@ -19,7 +19,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestFieldType.h"
 #include "Lucy/Test/TestUtils.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestFieldType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldType.cfh b/core/Lucy/Test/Plan/TestFieldType.cfh
index f91ec94..2632b6f 100644
--- a/core/Lucy/Test/Plan/TestFieldType.cfh
+++ b/core/Lucy/Test/Plan/TestFieldType.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Plan::TestFieldType cnick TestFType
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFieldType*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestFullTextType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFullTextType.c b/core/Lucy/Test/Plan/TestFullTextType.c
index cf8ef8f..9ad706b 100644
--- a/core/Lucy/Test/Plan/TestFullTextType.c
+++ b/core/Lucy/Test/Plan/TestFullTextType.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestFullTextType.h"
 #include "Lucy/Test/TestUtils.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestFullTextType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFullTextType.cfh b/core/Lucy/Test/Plan/TestFullTextType.cfh
index 91b9f30..47b9592 100644
--- a/core/Lucy/Test/Plan/TestFullTextType.cfh
+++ b/core/Lucy/Test/Plan/TestFullTextType.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Plan::TestFullTextType
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFullTextType*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestNumericType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestNumericType.c b/core/Lucy/Test/Plan/TestNumericType.c
index cdc42b5..48ef96c 100644
--- a/core/Lucy/Test/Plan/TestNumericType.c
+++ b/core/Lucy/Test/Plan/TestNumericType.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestNumericType.h"
 #include "Lucy/Test/TestUtils.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Plan/TestNumericType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestNumericType.cfh b/core/Lucy/Test/Plan/TestNumericType.cfh
index 72f7823..21c4b31 100644
--- a/core/Lucy/Test/Plan/TestNumericType.cfh
+++ b/core/Lucy/Test/Plan/TestNumericType.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Plan::TestNumericType
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNumericType*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestLeafQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestLeafQuery.c b/core/Lucy/Test/Search/TestLeafQuery.c
index 7dd37f8..ba7db58 100644
--- a/core/Lucy/Test/Search/TestLeafQuery.c
+++ b/core/Lucy/Test/Search/TestLeafQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestLeafQuery.h"
 #include "Lucy/Test/TestUtils.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestLeafQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestLeafQuery.cfh b/core/Lucy/Test/Search/TestLeafQuery.cfh
index 7bb03ab..19a9da3 100644
--- a/core/Lucy/Test/Search/TestLeafQuery.cfh
+++ b/core/Lucy/Test/Search/TestLeafQuery.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestLeafQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestLeafQuery*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestMatchAllQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestMatchAllQuery.c b/core/Lucy/Test/Search/TestMatchAllQuery.c
index 57f395b..b70c8f2 100644
--- a/core/Lucy/Test/Search/TestMatchAllQuery.c
+++ b/core/Lucy/Test/Search/TestMatchAllQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestMatchAllQuery.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestMatchAllQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestMatchAllQuery.cfh b/core/Lucy/Test/Search/TestMatchAllQuery.cfh
index 1f09bc1..1d2a3f5 100644
--- a/core/Lucy/Test/Search/TestMatchAllQuery.cfh
+++ b/core/Lucy/Test/Search/TestMatchAllQuery.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestMatchAllQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestMatchAllQuery*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestNOTQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNOTQuery.c b/core/Lucy/Test/Search/TestNOTQuery.c
index 374fd3d..c6b7246 100644
--- a/core/Lucy/Test/Search/TestNOTQuery.c
+++ b/core/Lucy/Test/Search/TestNOTQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestNOTQuery.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestNOTQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNOTQuery.cfh b/core/Lucy/Test/Search/TestNOTQuery.cfh
index becf64e..a2549d3 100644
--- a/core/Lucy/Test/Search/TestNOTQuery.cfh
+++ b/core/Lucy/Test/Search/TestNOTQuery.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestNOTQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNOTQuery*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestNoMatchQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNoMatchQuery.c b/core/Lucy/Test/Search/TestNoMatchQuery.c
index a1a9e20..76a738e 100644
--- a/core/Lucy/Test/Search/TestNoMatchQuery.c
+++ b/core/Lucy/Test/Search/TestNoMatchQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestNoMatchQuery.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestNoMatchQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNoMatchQuery.cfh b/core/Lucy/Test/Search/TestNoMatchQuery.cfh
index a283efa..9b2344d 100644
--- a/core/Lucy/Test/Search/TestNoMatchQuery.cfh
+++ b/core/Lucy/Test/Search/TestNoMatchQuery.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestNoMatchQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNoMatchQuery*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestPhraseQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPhraseQuery.c b/core/Lucy/Test/Search/TestPhraseQuery.c
index 3f07f9d..d350f95 100644
--- a/core/Lucy/Test/Search/TestPhraseQuery.c
+++ b/core/Lucy/Test/Search/TestPhraseQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestPhraseQuery.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestPhraseQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPhraseQuery.cfh b/core/Lucy/Test/Search/TestPhraseQuery.cfh
index c39290a..d1fcd07 100644
--- a/core/Lucy/Test/Search/TestPhraseQuery.cfh
+++ b/core/Lucy/Test/Search/TestPhraseQuery.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestPhraseQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPhraseQuery*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestPolyQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPolyQuery.c b/core/Lucy/Test/Search/TestPolyQuery.c
index 531bb3c..370f646 100644
--- a/core/Lucy/Test/Search/TestPolyQuery.c
+++ b/core/Lucy/Test/Search/TestPolyQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestPolyQuery.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestPolyQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPolyQuery.cfh b/core/Lucy/Test/Search/TestPolyQuery.cfh
index 768e8c4..b509286 100644
--- a/core/Lucy/Test/Search/TestPolyQuery.cfh
+++ b/core/Lucy/Test/Search/TestPolyQuery.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestANDQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestANDQuery*
     new(TestFormatter *formatter);
@@ -30,7 +30,7 @@ class Lucy::Test::Search::TestANDQuery
 }
 
 class Lucy::Test::Search::TestORQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestORQuery*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestQueryParserLogic.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserLogic.c b/core/Lucy/Test/Search/TestQueryParserLogic.c
index 0d88816..5e807a7 100644
--- a/core/Lucy/Test/Search/TestQueryParserLogic.c
+++ b/core/Lucy/Test/Search/TestQueryParserLogic.c
@@ -20,7 +20,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <string.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestQueryParserLogic.h"
 #include "Lucy/Test/Search/TestQueryParser.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestQueryParserLogic.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserLogic.cfh b/core/Lucy/Test/Search/TestQueryParserLogic.cfh
index 5f28b54..888e1ae 100644
--- a/core/Lucy/Test/Search/TestQueryParserLogic.cfh
+++ b/core/Lucy/Test/Search/TestQueryParserLogic.cfh
@@ -20,7 +20,7 @@ parcel TestLucy;
  */
 
 class Lucy::Test::Search::TestQueryParserLogic cnick TestQPLogic
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestQueryParserLogic*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestQueryParserSyntax.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserSyntax.c b/core/Lucy/Test/Search/TestQueryParserSyntax.c
index ededff1..06db2d5 100644
--- a/core/Lucy/Test/Search/TestQueryParserSyntax.c
+++ b/core/Lucy/Test/Search/TestQueryParserSyntax.c
@@ -20,7 +20,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <string.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestQueryParserSyntax.h"
 #include "Lucy/Test/Search/TestQueryParser.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserSyntax.cfh b/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
index 794dbe7..080fd4a 100644
--- a/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
+++ b/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
@@ -20,7 +20,7 @@ parcel TestLucy;
  */
 
 class Lucy::Test::Search::TestQueryParserSyntax cnick TestQPSyntax
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestQueryParserSyntax*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestRangeQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestRangeQuery.c b/core/Lucy/Test/Search/TestRangeQuery.c
index 7d76eee..fa1c698 100644
--- a/core/Lucy/Test/Search/TestRangeQuery.c
+++ b/core/Lucy/Test/Search/TestRangeQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestRangeQuery.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestRangeQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestRangeQuery.cfh b/core/Lucy/Test/Search/TestRangeQuery.cfh
index 41e98d3..241395d 100644
--- a/core/Lucy/Test/Search/TestRangeQuery.cfh
+++ b/core/Lucy/Test/Search/TestRangeQuery.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestRangeQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRangeQuery*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestReqOptQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestReqOptQuery.c b/core/Lucy/Test/Search/TestReqOptQuery.c
index f32bc5d..a974c4a 100644
--- a/core/Lucy/Test/Search/TestReqOptQuery.c
+++ b/core/Lucy/Test/Search/TestReqOptQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestReqOptQuery.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestReqOptQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestReqOptQuery.cfh b/core/Lucy/Test/Search/TestReqOptQuery.cfh
index b783734..4e50151 100644
--- a/core/Lucy/Test/Search/TestReqOptQuery.cfh
+++ b/core/Lucy/Test/Search/TestReqOptQuery.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestReqOptQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestReqOptQuery*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestSeriesMatcher.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSeriesMatcher.c b/core/Lucy/Test/Search/TestSeriesMatcher.c
index e3e68db..24ff6aa 100644
--- a/core/Lucy/Test/Search/TestSeriesMatcher.c
+++ b/core/Lucy/Test/Search/TestSeriesMatcher.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestSeriesMatcher.h"
 #include "Lucy/Search/BitVecMatcher.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestSeriesMatcher.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSeriesMatcher.cfh b/core/Lucy/Test/Search/TestSeriesMatcher.cfh
index 5952ce6..476156f 100644
--- a/core/Lucy/Test/Search/TestSeriesMatcher.cfh
+++ b/core/Lucy/Test/Search/TestSeriesMatcher.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestSeriesMatcher
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSeriesMatcher*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestSortSpec.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSortSpec.c b/core/Lucy/Test/Search/TestSortSpec.c
index a8b1e3e..e889b0e 100644
--- a/core/Lucy/Test/Search/TestSortSpec.c
+++ b/core/Lucy/Test/Search/TestSortSpec.c
@@ -21,7 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestSortSpec.h"
 #include "Lucy/Test/TestUtils.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestSortSpec.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSortSpec.cfh b/core/Lucy/Test/Search/TestSortSpec.cfh
index 633b452..e5be81e 100644
--- a/core/Lucy/Test/Search/TestSortSpec.cfh
+++ b/core/Lucy/Test/Search/TestSortSpec.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestSortSpec
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSortSpec*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestSpan.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSpan.c b/core/Lucy/Test/Search/TestSpan.c
index d359dbe..c2f9d60 100644
--- a/core/Lucy/Test/Search/TestSpan.c
+++ b/core/Lucy/Test/Search/TestSpan.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestSpan.h"
 #include "Lucy/Search/Span.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestSpan.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSpan.cfh b/core/Lucy/Test/Search/TestSpan.cfh
index 1c9a119..bc64c8e 100644
--- a/core/Lucy/Test/Search/TestSpan.cfh
+++ b/core/Lucy/Test/Search/TestSpan.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestSpan
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSpan*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestTermQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestTermQuery.c b/core/Lucy/Test/Search/TestTermQuery.c
index 809c440..46ddf04 100644
--- a/core/Lucy/Test/Search/TestTermQuery.c
+++ b/core/Lucy/Test/Search/TestTermQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestTermQuery.h"
 #include "Lucy/Test/TestUtils.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Search/TestTermQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestTermQuery.cfh b/core/Lucy/Test/Search/TestTermQuery.cfh
index 96e5d09..3cdcac2 100644
--- a/core/Lucy/Test/Search/TestTermQuery.cfh
+++ b/core/Lucy/Test/Search/TestTermQuery.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Search::TestTermQuery
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestTermQuery*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestCompoundFileReader.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileReader.c b/core/Lucy/Test/Store/TestCompoundFileReader.c
index f3748be..425611c 100644
--- a/core/Lucy/Test/Store/TestCompoundFileReader.c
+++ b/core/Lucy/Test/Store/TestCompoundFileReader.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestCompoundFileReader.h"
 #include "Lucy/Store/CompoundFileReader.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestCompoundFileReader.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileReader.cfh b/core/Lucy/Test/Store/TestCompoundFileReader.cfh
index f12c05b..bd2a23b 100644
--- a/core/Lucy/Test/Store/TestCompoundFileReader.cfh
+++ b/core/Lucy/Test/Store/TestCompoundFileReader.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestCompoundFileReader cnick TestCFReader
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestCompoundFileReader*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestCompoundFileWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileWriter.c b/core/Lucy/Test/Store/TestCompoundFileWriter.c
index 76dc72c..c315ba1 100644
--- a/core/Lucy/Test/Store/TestCompoundFileWriter.c
+++ b/core/Lucy/Test/Store/TestCompoundFileWriter.c
@@ -17,7 +17,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestCompoundFileWriter.h"
 #include "Lucy/Store/CompoundFileWriter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileWriter.cfh b/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
index f1ca473..407e6d7 100644
--- a/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
+++ b/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestCompoundFileWriter cnick TestCFWriter
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestCompoundFileWriter*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFSDirHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSDirHandle.c b/core/Lucy/Test/Store/TestFSDirHandle.c
index da9f9ff..59530ce 100644
--- a/core/Lucy/Test/Store/TestFSDirHandle.c
+++ b/core/Lucy/Test/Store/TestFSDirHandle.c
@@ -27,7 +27,7 @@
   #include <unistd.h>
 #endif
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFSDirHandle.h"
 #include "Lucy/Store/FSDirHandle.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFSDirHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSDirHandle.cfh b/core/Lucy/Test/Store/TestFSDirHandle.cfh
index d76dabb..33ae342 100644
--- a/core/Lucy/Test/Store/TestFSDirHandle.cfh
+++ b/core/Lucy/Test/Store/TestFSDirHandle.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestFSDirHandle cnick TestFSDH
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFSDirHandle*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFSFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFileHandle.c b/core/Lucy/Test/Store/TestFSFileHandle.c
index 34048a3..838d86d 100644
--- a/core/Lucy/Test/Store/TestFSFileHandle.c
+++ b/core/Lucy/Test/Store/TestFSFileHandle.c
@@ -27,7 +27,7 @@
   #include <io.h> // close
 #endif
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFSFileHandle.h"
 #include "Lucy/Store/FSFileHandle.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFSFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFileHandle.cfh b/core/Lucy/Test/Store/TestFSFileHandle.cfh
index 6fd288c..5eb2d86 100644
--- a/core/Lucy/Test/Store/TestFSFileHandle.cfh
+++ b/core/Lucy/Test/Store/TestFSFileHandle.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestFSFileHandle cnick TestFSFH
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFSFileHandle*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFSFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFolder.c b/core/Lucy/Test/Store/TestFSFolder.c
index d85deef..a64df50 100644
--- a/core/Lucy/Test/Store/TestFSFolder.c
+++ b/core/Lucy/Test/Store/TestFSFolder.c
@@ -32,7 +32,7 @@
   #include <sys/stat.h>
 #endif
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFSFolder.h"
 #include "Lucy/Test/Store/TestFolderCommon.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFSFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFolder.cfh b/core/Lucy/Test/Store/TestFSFolder.cfh
index 896e813..f590315 100644
--- a/core/Lucy/Test/Store/TestFSFolder.cfh
+++ b/core/Lucy/Test/Store/TestFSFolder.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestFSFolder
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFSFolder*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFileHandle.c b/core/Lucy/Test/Store/TestFileHandle.c
index 645b516..47afb43 100644
--- a/core/Lucy/Test/Store/TestFileHandle.c
+++ b/core/Lucy/Test/Store/TestFileHandle.c
@@ -20,7 +20,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFileHandle.h"
 #include "Lucy/Store/FileHandle.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFileHandle.cfh b/core/Lucy/Test/Store/TestFileHandle.cfh
index 8e852ba..d77eaa6 100644
--- a/core/Lucy/Test/Store/TestFileHandle.cfh
+++ b/core/Lucy/Test/Store/TestFileHandle.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestFileHandle cnick TestFH
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFileHandle*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolder.c b/core/Lucy/Test/Store/TestFolder.c
index 75eb6e6..ce7d417 100644
--- a/core/Lucy/Test/Store/TestFolder.c
+++ b/core/Lucy/Test/Store/TestFolder.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFolder.h"
 #include "Lucy/Store/DirHandle.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolder.cfh b/core/Lucy/Test/Store/TestFolder.cfh
index 09e4c2b..b9b3bb9 100644
--- a/core/Lucy/Test/Store/TestFolder.cfh
+++ b/core/Lucy/Test/Store/TestFolder.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestFolder
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFolder*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestFolderCommon.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolderCommon.c b/core/Lucy/Test/Store/TestFolderCommon.c
index ddbb421..c2ba9a4 100644
--- a/core/Lucy/Test/Store/TestFolderCommon.c
+++ b/core/Lucy/Test/Store/TestFolderCommon.c
@@ -19,7 +19,7 @@
 
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFolderCommon.h"
-#include "Clownfish/Test/TestBatch.h"
+#include "Clownfish/TestHarness/TestBatch.h"
 #include "Lucy/Store/Folder.h"
 #include "Lucy/Store/DirHandle.h"
 #include "Lucy/Store/FileHandle.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestIOChunks.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOChunks.c b/core/Lucy/Test/Store/TestIOChunks.c
index 3f88a3d..cae365c 100644
--- a/core/Lucy/Test/Store/TestIOChunks.c
+++ b/core/Lucy/Test/Store/TestIOChunks.c
@@ -22,7 +22,7 @@
 
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Store/TestIOChunks.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestIOChunks.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOChunks.cfh b/core/Lucy/Test/Store/TestIOChunks.cfh
index 94e5813..1cae6a9 100644
--- a/core/Lucy/Test/Store/TestIOChunks.cfh
+++ b/core/Lucy/Test/Store/TestIOChunks.cfh
@@ -19,7 +19,7 @@ parcel TestLucy;
 /** Tests reading and writing of composite types using InStream/OutStream.
  */
 class Lucy::Test::Store::TestIOChunks
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestIOChunks*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestIOPrimitives.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOPrimitives.c b/core/Lucy/Test/Store/TestIOPrimitives.c
index 009043b..55e3c78 100644
--- a/core/Lucy/Test/Store/TestIOPrimitives.c
+++ b/core/Lucy/Test/Store/TestIOPrimitives.c
@@ -22,7 +22,7 @@
 
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Store/TestIOPrimitives.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestIOPrimitives.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOPrimitives.cfh b/core/Lucy/Test/Store/TestIOPrimitives.cfh
index 106f940..ddf7852 100644
--- a/core/Lucy/Test/Store/TestIOPrimitives.cfh
+++ b/core/Lucy/Test/Store/TestIOPrimitives.cfh
@@ -19,7 +19,7 @@ parcel TestLucy;
 /** Tests reading and writing of primitive types using InStream/OutStream.
  */
 class Lucy::Test::Store::TestIOPrimitives
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestIOPrimitives*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestInStream.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestInStream.c b/core/Lucy/Test/Store/TestInStream.c
index 95b2cb1..9a29002 100644
--- a/core/Lucy/Test/Store/TestInStream.c
+++ b/core/Lucy/Test/Store/TestInStream.c
@@ -20,7 +20,7 @@
 
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Store/TestInStream.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestInStream.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestInStream.cfh b/core/Lucy/Test/Store/TestInStream.cfh
index 5052685..7b97094 100644
--- a/core/Lucy/Test/Store/TestInStream.cfh
+++ b/core/Lucy/Test/Store/TestInStream.cfh
@@ -21,7 +21,7 @@ parcel TestLucy;
  */
 
 class Lucy::Test::Store::TestInStream
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestInStream*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestRAMDirHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMDirHandle.c b/core/Lucy/Test/Store/TestRAMDirHandle.c
index fcdcd1a..7997aa2 100644
--- a/core/Lucy/Test/Store/TestRAMDirHandle.c
+++ b/core/Lucy/Test/Store/TestRAMDirHandle.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestRAMDirHandle.h"
 #include "Lucy/Store/FileHandle.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestRAMDirHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMDirHandle.cfh b/core/Lucy/Test/Store/TestRAMDirHandle.cfh
index aabe232..ac80e4d 100644
--- a/core/Lucy/Test/Store/TestRAMDirHandle.cfh
+++ b/core/Lucy/Test/Store/TestRAMDirHandle.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestRAMDirHandle cnick TestRAMDH
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRAMDirHandle*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestRAMFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFileHandle.c b/core/Lucy/Test/Store/TestRAMFileHandle.c
index 5d75bc3..0289c79 100644
--- a/core/Lucy/Test/Store/TestRAMFileHandle.c
+++ b/core/Lucy/Test/Store/TestRAMFileHandle.c
@@ -22,7 +22,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestRAMFileHandle.h"
 #include "Lucy/Store/RAMFileHandle.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestRAMFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFileHandle.cfh b/core/Lucy/Test/Store/TestRAMFileHandle.cfh
index 8ee2c1d..2b64af1 100644
--- a/core/Lucy/Test/Store/TestRAMFileHandle.cfh
+++ b/core/Lucy/Test/Store/TestRAMFileHandle.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestRAMFileHandle cnick TestRAMFH
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRAMFileHandle*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestRAMFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFolder.c b/core/Lucy/Test/Store/TestRAMFolder.c
index 0446e9d..47a69b5 100644
--- a/core/Lucy/Test/Store/TestRAMFolder.c
+++ b/core/Lucy/Test/Store/TestRAMFolder.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestRAMFolder.h"
 #include "Lucy/Store/RAMFolder.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Store/TestRAMFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFolder.cfh b/core/Lucy/Test/Store/TestRAMFolder.cfh
index dfc3864..231e579 100644
--- a/core/Lucy/Test/Store/TestRAMFolder.cfh
+++ b/core/Lucy/Test/Store/TestRAMFolder.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Store::TestRAMFolder
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRAMFolder*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/TestSchema.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestSchema.c b/core/Lucy/Test/TestSchema.c
index 34029cd..847fa74 100644
--- a/core/Lucy/Test/TestSchema.c
+++ b/core/Lucy/Test/TestSchema.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestArchitecture.h"
 #include "Lucy/Test/TestSchema.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/TestSchema.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestSchema.cfh b/core/Lucy/Test/TestSchema.cfh
index decb6d5..758c707 100644
--- a/core/Lucy/Test/TestSchema.cfh
+++ b/core/Lucy/Test/TestSchema.cfh
@@ -34,7 +34,7 @@ class Lucy::Test::TestSchema inherits Lucy::Plan::Schema {
 }
 
 class Lucy::Test::TestBatchSchema
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestBatchSchema*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/TestUtils.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestUtils.c b/core/Lucy/Test/TestUtils.c
index d567e15..36f51f4 100644
--- a/core/Lucy/Test/TestUtils.c
+++ b/core/Lucy/Test/TestUtils.c
@@ -21,7 +21,7 @@
 
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test.h"
-#include "Clownfish/Test/TestBatch.h"
+#include "Clownfish/TestHarness/TestBatch.h"
 #include "Lucy/Analysis/Analyzer.h"
 #include "Lucy/Analysis/Inversion.h"
 #include "Lucy/Analysis/Token.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Util/TestIndexFileNames.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestIndexFileNames.c b/core/Lucy/Test/Util/TestIndexFileNames.c
index 95e0f3f..5f7e41a 100644
--- a/core/Lucy/Test/Util/TestIndexFileNames.c
+++ b/core/Lucy/Test/Util/TestIndexFileNames.c
@@ -17,7 +17,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Util/TestIndexFileNames.h"
 #include "Lucy/Util/IndexFileNames.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Util/TestIndexFileNames.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestIndexFileNames.cfh b/core/Lucy/Test/Util/TestIndexFileNames.cfh
index 8e106b7..44323de 100644
--- a/core/Lucy/Test/Util/TestIndexFileNames.cfh
+++ b/core/Lucy/Test/Util/TestIndexFileNames.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Util::TestIndexFileNames cnick TestIxFileNames
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestIndexFileNames*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Util/TestJson.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestJson.c b/core/Lucy/Test/Util/TestJson.c
index 6d379a2..7be389a 100644
--- a/core/Lucy/Test/Util/TestJson.c
+++ b/core/Lucy/Test/Util/TestJson.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Util/TestJson.h"
 #include "Lucy/Util/Json.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Util/TestJson.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestJson.cfh b/core/Lucy/Test/Util/TestJson.cfh
index 0bf2e2f..f077492 100644
--- a/core/Lucy/Test/Util/TestJson.cfh
+++ b/core/Lucy/Test/Util/TestJson.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Util::TestJson
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestJson*
     new(TestFormatter *formatter);


[lucy-commits] [12/26] git commit: refs/heads/separate-clownfish-wip2 - Support object types from other parcels without prefix

Posted by nw...@apache.org.
Support object types from other parcels without prefix

Resolve types after all classes have been parsed.

This means that caching of C representations has to be postponed. For
now, the C representations are cached after the types have been
resolved. This is error-prone and requires some hacks for methods. It
might be better to move to a scheme where the C strings are not cached
until they're used for the first time.

TODO: Add Perl bindings and fix Perl tests


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/fa4918d2
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/fa4918d2
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/fa4918d2

Branch: refs/heads/separate-clownfish-wip2
Commit: fa4918d2c11e1cf600579a977f8e752227dc5d2f
Parents: cecd524
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 20 01:36:52 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:17 2013 +0200

----------------------------------------------------------------------
 clownfish/compiler/src/CFCClass.c         |   16 +++
 clownfish/compiler/src/CFCClass.h         |    5 +
 clownfish/compiler/src/CFCDumpable.c      |   13 ++-
 clownfish/compiler/src/CFCFunction.c      |    6 +
 clownfish/compiler/src/CFCFunction.h      |    6 +
 clownfish/compiler/src/CFCHierarchy.c     |    3 +
 clownfish/compiler/src/CFCMethod.c        |   30 ++++--
 clownfish/compiler/src/CFCMethod.h        |    3 +
 clownfish/compiler/src/CFCParamList.c     |   14 ++-
 clownfish/compiler/src/CFCParamList.h     |    4 +
 clownfish/compiler/src/CFCTest.c          |    6 +
 clownfish/compiler/src/CFCTestClass.c     |   15 +++-
 clownfish/compiler/src/CFCTestFile.c      |   22 ++++-
 clownfish/compiler/src/CFCTestMethod.c    |   12 ++-
 clownfish/compiler/src/CFCTestParamList.c |   10 ++-
 clownfish/compiler/src/CFCTestParser.c    |   15 +++-
 clownfish/compiler/src/CFCTestType.c      |   36 +++++++-
 clownfish/compiler/src/CFCTestVariable.c  |   10 ++-
 clownfish/compiler/src/CFCType.c          |  123 ++++++++++++++++--------
 clownfish/compiler/src/CFCType.h          |    6 +
 clownfish/compiler/src/CFCVariable.c      |   18 +++-
 clownfish/compiler/src/CFCVariable.h      |    4 +
 22 files changed, 303 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCClass.c b/clownfish/compiler/src/CFCClass.c
index e5022ac..0567ca4 100644
--- a/clownfish/compiler/src/CFCClass.c
+++ b/clownfish/compiler/src/CFCClass.c
@@ -459,6 +459,22 @@ CFCClass_fresh_method(CFCClass *self, const char *sym) {
     return NULL;
 }
 
+void
+CFCClass_resolve_types(CFCClass *self, CFCClass **classes) {
+    for (size_t i = 0; self->functions[i] != NULL; i++) {
+        CFCFunction_resolve_types(self->functions[i], classes);
+    }
+    for (size_t i = 0; self->methods[i] != NULL; i++) {
+        CFCMethod_resolve_types(self->methods[i], classes);
+    }
+    for (size_t i = 0; self->member_vars[i] != NULL; i++) {
+        CFCVariable_resolve_type(self->member_vars[i], classes);
+    }
+    for (size_t i = 0; self->inert_vars[i] != NULL; i++) {
+        CFCVariable_resolve_type(self->inert_vars[i], classes);
+    }
+}
+
 // Pass down member vars to from parent to children.
 static void
 S_bequeath_member_vars(CFCClass *self) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCClass.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCClass.h b/clownfish/compiler/src/CFCClass.h
index fd38149..cb484d8 100644
--- a/clownfish/compiler/src/CFCClass.h
+++ b/clownfish/compiler/src/CFCClass.h
@@ -150,6 +150,11 @@ CFCClass_fresh_method(CFCClass *self, const char *sym);
 struct CFCMethod*
 CFCClass_find_novel_method(CFCClass *self, const char *sym);
 
+/** Find the actual class of all object variables without prefix.
+ */
+void
+CFCClass_resolve_types(CFCClass *self, CFCClass **classes);
+
 /** Bequeath all inherited methods and members to children.
  */
 void

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCDumpable.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCDumpable.c b/clownfish/compiler/src/CFCDumpable.c
index 7fd2616..006f62a 100644
--- a/clownfish/compiler/src/CFCDumpable.c
+++ b/clownfish/compiler/src/CFCDumpable.c
@@ -110,14 +110,15 @@ CFCDumpable_add_dumpables(CFCDumpable *self, CFCClass *klass) {
 
 static CFCMethod*
 S_make_method_obj(CFCClass *klass, const char *method_name) {
-    const char *klass_struct_sym = CFCClass_get_struct_sym(klass);
+    const char *klass_full_struct_sym = CFCClass_full_struct_sym(klass);
     const char *klass_name   = CFCClass_get_class_name(klass);
     const char *klass_cnick  = CFCClass_get_cnick(klass);
     CFCParcel  *klass_parcel = CFCClass_get_parcel(klass);
 
     CFCType *return_type
-        = CFCType_new_object(CFCTYPE_INCREMENTED, klass_parcel, "Obj", 1);
-    CFCType *self_type = CFCType_new_object(0, klass_parcel, klass_struct_sym, 1);
+        = CFCType_new_object(CFCTYPE_INCREMENTED, klass_parcel, "lucy_Obj", 1);
+    CFCType *self_type = CFCType_new_object(0, klass_parcel,
+                                            klass_full_struct_sym, 1);
     CFCVariable *self_var = CFCVariable_new(NULL, NULL, NULL, NULL, "self",
                                             self_type, false);
     CFCParamList *param_list = NULL;
@@ -127,7 +128,8 @@ S_make_method_obj(CFCClass *klass, const char *method_name) {
         CFCParamList_add_param(param_list, self_var, NULL);
     }
     else if (strcmp(method_name, "Load") == 0) {
-        CFCType *dump_type = CFCType_new_object(0, klass_parcel, "Obj", 1);
+        CFCType *dump_type = CFCType_new_object(0, klass_parcel, "lucy_Obj",
+                                                1);
         CFCVariable *dump_var = CFCVariable_new(NULL, NULL, NULL, NULL, "dump",
                                                 dump_type, false);
         param_list = CFCParamList_new(false);
@@ -143,6 +145,9 @@ S_make_method_obj(CFCClass *klass, const char *method_name) {
     CFCMethod *method = CFCMethod_new(klass_parcel, "public", klass_name,
                                       klass_cnick, method_name, return_type,
                                       param_list, NULL, false, false);
+    // Hack
+    CFCClass *dummy_class = NULL;
+    CFCMethod_resolve_types(method, &dummy_class);
 
     CFCBase_decref((CFCBase*)param_list);
     CFCBase_decref((CFCBase*)self_type);

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCFunction.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCFunction.c b/clownfish/compiler/src/CFCFunction.c
index 7205622..6f781f4 100644
--- a/clownfish/compiler/src/CFCFunction.c
+++ b/clownfish/compiler/src/CFCFunction.c
@@ -84,6 +84,12 @@ CFCFunction_init(CFCFunction *self, CFCParcel *parcel, const char *exposure,
 }
 
 void
+CFCFunction_resolve_types(CFCFunction *self, struct CFCClass **classes) {
+    CFCType_resolve(self->return_type, classes);
+    CFCParamList_resolve_types(self->param_list, classes);
+}
+
+void
 CFCFunction_destroy(CFCFunction *self) {
     CFCBase_decref((CFCBase*)self->return_type);
     CFCBase_decref((CFCBase*)self->param_list);

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCFunction.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCFunction.h b/clownfish/compiler/src/CFCFunction.h
index e69b632..baab2c7 100644
--- a/clownfish/compiler/src/CFCFunction.h
+++ b/clownfish/compiler/src/CFCFunction.h
@@ -29,6 +29,7 @@ struct CFCParcel;
 struct CFCType;
 struct CFCDocuComment;
 struct CFCParamList;
+struct CFCClass;
 
 #ifdef CFC_NEED_FUNCTION_STRUCT_DEF
 #define CFC_NEED_SYMBOL_STRUCT_DEF
@@ -110,6 +111,11 @@ CFCFunction_micro_sym(CFCFunction *self);
 int
 CFCFunction_public(CFCFunction *self);
 
+/** Find the actual class of all object variables without prefix.
+ */
+void
+CFCFunction_resolve_types(CFCFunction *self, struct CFCClass **classes);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCHierarchy.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCHierarchy.c b/clownfish/compiler/src/CFCHierarchy.c
index b8ba423..5c5b192 100644
--- a/clownfish/compiler/src/CFCHierarchy.c
+++ b/clownfish/compiler/src/CFCHierarchy.c
@@ -197,6 +197,9 @@ CFCHierarchy_build(CFCHierarchy *self) {
     for (size_t i = 0; self->includes[i] != NULL; i++) {
         S_parse_cf_files(self, self->includes[i], 1);
     }
+    for (int i = 0; self->classes[i] != NULL; i++) {
+        CFCClass_resolve_types(self->classes[i], self->classes);
+    }
     S_connect_classes(self);
     for (size_t i = 0; self->trees[i] != NULL; i++) {
         CFCClass_grow_tree(self->trees[i]);

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCMethod.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCMethod.c b/clownfish/compiler/src/CFCMethod.c
index a9f0063..f659323 100644
--- a/clownfish/compiler/src/CFCMethod.c
+++ b/clownfish/compiler/src/CFCMethod.c
@@ -105,12 +105,30 @@ CFCMethod_init(CFCMethod *self, CFCParcel *parcel, const char *exposure,
                      docucomment, false);
     FREEMEM(micro_sym);
 
+    self->macro_sym     = CFCUtil_strdup(macro_sym);
+    self->is_final      = is_final;
+    self->is_abstract   = is_abstract;
+
+    self->full_override_sym = NULL;
+
+    // Assume that this method is novel until we discover when applying
+    // inheritance that it overrides another.
+    self->is_novel = true;
+
+    return self;
+}
+
+void
+CFCMethod_resolve_types(CFCMethod *self, struct CFCClass **classes) {
+    CFCFunction_resolve_types((CFCFunction*)self, classes);
+
     // Verify that the first element in the arg list is a self.
-    CFCVariable **args = CFCParamList_get_variables(param_list);
+    CFCVariable **args = CFCParamList_get_variables(self->function.param_list);
     if (!args[0]) { CFCUtil_die("Missing 'self' argument"); }
     CFCType *type = CFCVariable_get_type(args[0]);
     const char *specifier = CFCType_get_specifier(type);
     const char *prefix    = CFCMethod_get_prefix(self);
+    const char *class_name = CFCMethod_get_class_name(self);
     const char *last_colon = strrchr(class_name, ':');
     const char *struct_sym = last_colon ? last_colon + 1 : class_name;
     char *wanted = CFCUtil_sprintf("%s%s", prefix, struct_sym);
@@ -121,19 +139,9 @@ CFCMethod_init(CFCMethod *self, CFCParcel *parcel, const char *exposure,
                     class_name, specifier);
     }
 
-    self->macro_sym     = CFCUtil_strdup(macro_sym);
-    self->is_final      = is_final;
-    self->is_abstract   = is_abstract;
-
     // Derive more symbols.
     const char *full_func_sym = CFCMethod_implementing_func_sym(self);
     self->full_override_sym = CFCUtil_sprintf("%s_OVERRIDE", full_func_sym);
-
-    // Assume that this method is novel until we discover when applying
-    // inheritance that it overrides another.
-    self->is_novel = true;
-
-    return self;
 }
 
 void

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCMethod.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCMethod.h b/clownfish/compiler/src/CFCMethod.h
index b7f01dd..cdceb6a 100644
--- a/clownfish/compiler/src/CFCMethod.h
+++ b/clownfish/compiler/src/CFCMethod.h
@@ -71,6 +71,9 @@ CFCMethod_init(CFCMethod *self, struct CFCParcel *parcel,
                int is_abstract);
 
 void
+CFCMethod_resolve_types(CFCMethod *self, struct CFCClass **classes);
+
+void
 CFCMethod_destroy(CFCMethod *self);
 
 /** Returns true if the methods have signatures and attributes which allow one

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCParamList.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParamList.c b/clownfish/compiler/src/CFCParamList.c
index 3e7bacf..2845480 100644
--- a/clownfish/compiler/src/CFCParamList.c
+++ b/clownfish/compiler/src/CFCParamList.c
@@ -55,11 +55,20 @@ CFCParamList_init(CFCParamList *self, int variadic) {
     self->num_vars  = 0;
     self->variables = (CFCVariable**)CALLOCATE(1, sizeof(void*));
     self->values    = (char**)CALLOCATE(1, sizeof(char*));
-    S_generate_c_strings(self);
+    self->c_string  = CFCUtil_strdup("");
+    self->name_list = CFCUtil_strdup("");
     return self;
 }
 
 void
+CFCParamList_resolve_types(CFCParamList *self, struct CFCClass **classes) {
+    for (size_t i = 0; self->variables[i]; ++i) {
+        CFCVariable_resolve_type(self->variables[i], classes);
+    }
+    S_generate_c_strings(self);
+}
+
+void
 CFCParamList_add_param(CFCParamList *self, CFCVariable *variable,
                        const char *value) {
     CFCUTIL_NULL_CHECK(variable);
@@ -72,8 +81,6 @@ CFCParamList_add_param(CFCParamList *self, CFCVariable *variable,
     self->values[self->num_vars - 1] = value ? CFCUtil_strdup(value) : NULL;
     self->variables[self->num_vars] = NULL;
     self->values[self->num_vars] = NULL;
-
-    S_generate_c_strings(self);
 }
 
 void
@@ -153,7 +160,6 @@ CFCParamList_num_vars(CFCParamList *self) {
 void
 CFCParamList_set_variadic(CFCParamList *self, int variadic) {
     self->variadic = !!variadic;
-    S_generate_c_strings(self);
 }
 
 int

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCParamList.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParamList.h b/clownfish/compiler/src/CFCParamList.h
index 23cc0e3..886fdfe 100644
--- a/clownfish/compiler/src/CFCParamList.h
+++ b/clownfish/compiler/src/CFCParamList.h
@@ -25,6 +25,7 @@ extern "C" {
 #endif
 
 typedef struct CFCParamList CFCParamList;
+struct CFCClass;
 struct CFCVariable;
 
 /**
@@ -37,6 +38,9 @@ CFCParamList*
 CFCParamList_init(CFCParamList *self, int variadic);
 
 void
+CFCParamList_resolve_types(CFCParamList *self, struct CFCClass **classes);
+
+void
 CFCParamList_destroy(CFCParamList *self);
 
 /** Add a parameter to the ParamList.

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCTest.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTest.c b/clownfish/compiler/src/CFCTest.c
index 2fd9933..21cff48 100644
--- a/clownfish/compiler/src/CFCTest.c
+++ b/clownfish/compiler/src/CFCTest.c
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -297,6 +298,11 @@ S_format_cfish_vtest_result(int pass, int test_num, const char *fmt,
         vprintf(fmt, args);
         printf("\n");
     }
+    else if (getenv("CFCTEST_VERBOSE")) {
+        printf("  Passed test %d: ", test_num);
+        vprintf(fmt, args);
+        printf("\n");
+    }
 }
 
 static void

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCTestClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestClass.c b/clownfish/compiler/src/CFCTestClass.c
index 67097d6..9f841f9 100644
--- a/clownfish/compiler/src/CFCTestClass.c
+++ b/clownfish/compiler/src/CFCTestClass.c
@@ -39,7 +39,7 @@ S_has_symbol(CFCSymbol **symbols, const char *micro_sym);
 
 const CFCTestBatch CFCTEST_BATCH_CLASS = {
     "Clownfish::CFC::Model::Class",
-    83,
+    87,
     S_run_tests
 };
 
@@ -49,6 +49,10 @@ S_run_tests(CFCTest *test) {
 
     CFCParcel *neato = CFCParcel_new("Neato", NULL, NULL);
     CFCFileSpec *file_spec = CFCFileSpec_new(".", "Foo/FooJr", 0);
+    CFCClass *thing_class
+        = CFCTest_parse_class(test, parser, "class Thing {}");
+    CFCClass *widget_class
+        = CFCTest_parse_class(test, parser, "class Widget {}");
 
     CFCVariable *thing;
     CFCVariable *widget;
@@ -119,6 +123,13 @@ S_run_tests(CFCTest *test) {
         = CFCTest_parse_method(test, parser, "void Do_Stuff(Foo *self);");
     CFCClass_add_method(foo, do_stuff);
 
+    CFCClass *class_list[6] = {
+        foo, foo_jr, final_foo, thing_class, widget_class, NULL
+    };
+    CFCClass_resolve_types(foo, class_list);
+    CFCClass_resolve_types(foo_jr, class_list);
+    CFCClass_resolve_types(final_foo, class_list);
+
     CFCClass_add_child(foo, foo_jr);
     CFCClass_add_child(foo_jr, final_foo);
     CFCClass_grow_tree(foo);
@@ -330,6 +341,8 @@ S_run_tests(CFCTest *test) {
     CFCBase_decref((CFCBase*)parser);
     CFCBase_decref((CFCBase*)neato);
     CFCBase_decref((CFCBase*)file_spec);
+    CFCBase_decref((CFCBase*)thing_class);
+    CFCBase_decref((CFCBase*)widget_class);
     CFCBase_decref((CFCBase*)thing);
     CFCBase_decref((CFCBase*)widget);
     CFCBase_decref((CFCBase*)tread_water);

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCTestFile.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestFile.c b/clownfish/compiler/src/CFCTestFile.c
index 2e1edc5..f62b919 100644
--- a/clownfish/compiler/src/CFCTestFile.c
+++ b/clownfish/compiler/src/CFCTestFile.c
@@ -21,6 +21,7 @@
 #include "CFCClass.h"
 #include "CFCFile.h"
 #include "CFCFileSpec.h"
+#include "CFCParcel.h"
 #include "CFCParser.h"
 #include "CFCTest.h"
 #include "CFCType.h"
@@ -32,7 +33,7 @@ S_run_tests(CFCTest *test);
 
 const CFCTestBatch CFCTEST_BATCH_FILE = {
     "Clownfish::CFC::Model::File",
-    19,
+    21,
     S_run_tests
 };
 
@@ -50,6 +51,8 @@ S_run_tests(CFCTest *test) {
             "    Foo *foo;\n"
             "    Bar *bar;\n"
             "}\n"
+            "class Foo {}\n"
+            "class Bar {}\n"
             "__C__\n"
             "int foo;\n"
             "__END_C__\n";
@@ -88,13 +91,17 @@ S_run_tests(CFCTest *test) {
         FREEMEM(h_path);
 
         CFCClass **classes = CFCFile_classes(file);
-        OK(test, classes[0] != NULL && classes[1] == NULL,
+        OK(test,
+           classes[0] != NULL && classes[1] != NULL && classes[2] != NULL
+           && classes[3] == NULL,
            "classes() filters blocks");
         CFCVariable **member_vars = CFCClass_member_vars(classes[0]);
         CFCType *foo_type = CFCVariable_get_type(member_vars[0]);
+        CFCType_resolve(foo_type, classes);
         STR_EQ(test, CFCType_get_specifier(foo_type), "stuff_Foo",
                "file production picked up parcel def");
         CFCType *bar_type = CFCVariable_get_type(member_vars[1]);
+        CFCType_resolve(bar_type, classes);
         STR_EQ(test, CFCType_get_specifier(bar_type), "stuff_Bar",
                "parcel def is sticky");
 
@@ -104,8 +111,12 @@ S_run_tests(CFCTest *test) {
         STR_EQ(test, CFCBase_get_cfc_class(blocks[1]),
                "Clownfish::CFC::Model::Class", "blocks[1]");
         STR_EQ(test, CFCBase_get_cfc_class(blocks[2]),
-               "Clownfish::CFC::Model::CBlock", "blocks[2]");
-        OK(test, blocks[3] == NULL, "blocks[3]");
+               "Clownfish::CFC::Model::Class", "blocks[2]");
+        STR_EQ(test, CFCBase_get_cfc_class(blocks[3]),
+               "Clownfish::CFC::Model::Class", "blocks[3]");
+        STR_EQ(test, CFCBase_get_cfc_class(blocks[4]),
+               "Clownfish::CFC::Model::CBlock", "blocks[4]");
+        OK(test, blocks[5] == NULL, "blocks[5]");
 
         CFCBase_decref((CFCBase*)file);
     }
@@ -128,5 +139,8 @@ S_run_tests(CFCTest *test) {
 
     CFCBase_decref((CFCBase*)file_spec);
     CFCBase_decref((CFCBase*)parser);
+
+    CFCClass_clear_registry();
+    CFCParcel_reap_singletons();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCTestMethod.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestMethod.c b/clownfish/compiler/src/CFCTestMethod.c
index 7122786..a805228 100644
--- a/clownfish/compiler/src/CFCTestMethod.c
+++ b/clownfish/compiler/src/CFCTestMethod.c
@@ -16,6 +16,7 @@
 
 #define CFC_USE_TEST_MACROS
 #include "CFCBase.h"
+#include "CFCClass.h"
 #include "CFCMethod.h"
 #include "CFCParamList.h"
 #include "CFCParcel.h"
@@ -41,7 +42,7 @@ S_run_final_tests(CFCTest *test);
 
 const CFCTestBatch CFCTEST_BATCH_METHOD = {
     "Clownfish::CFC::Model::Method",
-    66,
+    70,
     S_run_tests
 };
 
@@ -225,6 +226,11 @@ S_run_final_tests(CFCTest *test) {
     CFCParser *parser = CFCParser_new();
     CFCParcel *neato_parcel
         = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+    CFCClass *obj_class
+        = CFCTest_parse_class(test, parser, "class Obj {}");
+    CFCClass *foo_class
+        = CFCTest_parse_class(test, parser, "class Neato::Foo {}");
+    CFCClass *class_list[3] = { obj_class, foo_class, NULL };
     CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*");
     CFCParamList *param_list
         = CFCTest_parse_param_list(test, parser, "(Foo *self)");
@@ -233,6 +239,7 @@ S_run_final_tests(CFCTest *test) {
         = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo",
                         "Return_An_Obj", return_type, param_list,
                         NULL, 0, 0);
+    CFCMethod_resolve_types(not_final, class_list);
     CFCMethod *final = CFCMethod_finalize(not_final);
     OK(test, CFCMethod_compatible(not_final, final),
        "finalize clones properly");
@@ -241,11 +248,14 @@ S_run_final_tests(CFCTest *test) {
 
     CFCBase_decref((CFCBase*)parser);
     CFCBase_decref((CFCBase*)neato_parcel);
+    CFCBase_decref((CFCBase*)obj_class);
+    CFCBase_decref((CFCBase*)foo_class);
     CFCBase_decref((CFCBase*)return_type);
     CFCBase_decref((CFCBase*)param_list);
     CFCBase_decref((CFCBase*)not_final);
     CFCBase_decref((CFCBase*)final);
 
+    CFCClass_clear_registry();
     CFCParcel_reap_singletons();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCTestParamList.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestParamList.c b/clownfish/compiler/src/CFCTestParamList.c
index 0fd552c..29ff226 100644
--- a/clownfish/compiler/src/CFCTestParamList.c
+++ b/clownfish/compiler/src/CFCTestParamList.c
@@ -16,6 +16,7 @@
 
 #define CFC_USE_TEST_MACROS
 #include "CFCBase.h"
+#include "CFCClass.h"
 #include "CFCParamList.h"
 #include "CFCParcel.h"
 #include "CFCParser.h"
@@ -27,7 +28,7 @@ S_run_tests(CFCTest *test);
 
 const CFCTestBatch CFCTEST_BATCH_PARAM_LIST = {
     "Clownfish::CFC::Model::ParamList",
-    21,
+    23,
     S_run_tests
 };
 
@@ -36,10 +37,13 @@ S_run_tests(CFCTest *test) {
     CFCParser *parser = CFCParser_new();
     CFCParcel *neato_parcel
         = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+    CFCClass *obj_class = CFCTest_parse_class(test, parser, "class Obj {}");
+    CFCClass *class_list[2] = { obj_class, NULL };
 
     {
         CFCParamList *param_list
             = CFCTest_parse_param_list(test, parser, "(Obj *self, int num)");
+        CFCParamList_resolve_types(param_list, class_list);
         OK(test, !CFCParamList_variadic(param_list), "not variadic");
         STR_EQ(test, CFCParamList_to_c(param_list), "neato_Obj* self, int num",
                "to_c");
@@ -53,6 +57,7 @@ S_run_tests(CFCTest *test) {
         CFCParamList *param_list
             = CFCTest_parse_param_list(test, parser,
                                        "(Obj *self=NULL, int num, ...)");
+        CFCParamList_resolve_types(param_list, class_list);
         OK(test, CFCParamList_variadic(param_list), "variadic");
         STR_EQ(test, CFCParamList_to_c(param_list),
                "neato_Obj* self, int num, ...", "to_c");
@@ -72,6 +77,7 @@ S_run_tests(CFCTest *test) {
     {
         CFCParamList *param_list
             = CFCTest_parse_param_list(test, parser, "()");
+        CFCParamList_resolve_types(param_list, class_list);
         STR_EQ(test, CFCParamList_to_c(param_list), "void", "to_c");
         INT_EQ(test, CFCParamList_num_vars(param_list), 0, "num_vars");
         CFCVariable **variables = CFCParamList_get_variables(param_list);
@@ -82,7 +88,9 @@ S_run_tests(CFCTest *test) {
 
     CFCBase_decref((CFCBase*)parser);
     CFCBase_decref((CFCBase*)neato_parcel);
+    CFCBase_decref((CFCBase*)obj_class);
 
+    CFCClass_clear_registry();
     CFCParcel_reap_singletons();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCTestParser.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestParser.c b/clownfish/compiler/src/CFCTestParser.c
index 35d38ab..46611dd 100644
--- a/clownfish/compiler/src/CFCTestParser.c
+++ b/clownfish/compiler/src/CFCTestParser.c
@@ -37,7 +37,7 @@ S_test_initial_value(CFCTest *test, CFCParser *parser,
 
 const CFCTestBatch CFCTEST_BATCH_PARSER = {
     "Clownfish::CFC::Model::Parser",
-    189,
+    203,
     S_run_tests
 };
 
@@ -108,17 +108,30 @@ S_run_tests(CFCTest *test) {
         static const char *const class_names[7] = {
             "ByteBuf", "Obj", "ANDMatcher", "Foo", "FooJr", "FooIII", "Foo4th"
         };
+        CFCClass *class_list[8];
+        for (int i = 0; i < 7; ++i) {
+            char *class_code = CFCUtil_sprintf("class %s {}", class_names[i]);
+            CFCClass *klass = CFCTest_parse_class(test, parser, class_code);
+            class_list[i] = klass;
+            FREEMEM(class_code);
+        }
+        class_list[7] = NULL;
         for (int i = 0; i < 7; ++i) {
             const char *class_name = class_names[i];
             char *src      = CFCUtil_sprintf("%s*", class_name);
             char *expected = CFCUtil_sprintf("crust_%s", class_name);
             CFCType *type = CFCTest_parse_type(test, parser, src);
+            CFCType_resolve(type, class_list);
             STR_EQ(test, CFCType_get_specifier(type), expected,
                    "object_type_specifier: %s", class_name);
             FREEMEM(src);
             FREEMEM(expected);
             CFCBase_decref((CFCBase*)type);
         }
+        for (int i = 0; i < 7; ++i) {
+            CFCBase_decref((CFCBase*)class_list[i]);
+        }
+        CFCClass_clear_registry();
     }
 
     {

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCTestType.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestType.c b/clownfish/compiler/src/CFCTestType.c
index 8751eb8..759aa42 100644
--- a/clownfish/compiler/src/CFCTestType.c
+++ b/clownfish/compiler/src/CFCTestType.c
@@ -16,12 +16,18 @@
 
 #define CFC_USE_TEST_MACROS
 #include "CFCBase.h"
+#include "CFCClass.h"
 #include "CFCParcel.h"
 #include "CFCParser.h"
 #include "CFCTest.h"
 #include "CFCType.h"
 #include "CFCUtil.h"
 
+#ifndef true
+  #define true 1
+  #define false 0
+#endif
+
 static void
 S_run_tests(CFCTest *test);
 
@@ -54,7 +60,7 @@ S_run_composite_tests(CFCTest *test);
 
 const CFCTestBatch CFCTEST_BATCH_TYPE = {
     "Clownfish::CFC::Model::Type",
-    353,
+    361,
     S_run_tests
 };
 
@@ -287,11 +293,17 @@ S_run_object_tests(CFCTest *test) {
         for (int i = 0; i < 4; ++i) {
             const char *specifier = specifiers[i];
 
+            char *class_code = CFCUtil_sprintf("class %s {}", specifier);
+            CFCClass *klass = CFCTest_parse_class(test, parser, class_code);
+            CFCClass *class_list[2] = { klass, NULL };
+            FREEMEM(class_code);
+
             static const char *prefixes[2] = { "", "neato_" };
             char *expect = CFCUtil_sprintf("neato_%s", specifier);
             for (int j = 0; j < 2; ++j) {
                 char *src = CFCUtil_sprintf("%s%s*", prefixes[j], specifier);
                 CFCType *type = CFCTest_parse_type(test, parser, src);
+                CFCType_resolve(type, class_list);
                 STR_EQ(test, CFCType_get_specifier(type), expect,
                        "object_type_specifier: %s", src);
                 OK(test, CFCType_is_object(type), "%s is_object", src);
@@ -312,16 +324,26 @@ S_run_object_tests(CFCTest *test) {
                 FREEMEM(src);
                 CFCBase_decref((CFCBase*)type);
             }
+
+            CFCBase_decref((CFCBase*)klass);
+            CFCClass_clear_registry();
         }
 
         CFCBase_decref((CFCBase*)neato_parcel);
         CFCBase_decref((CFCBase*)parser);
     }
 
+    CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL);
+    CFCClass *foo_class
+        = CFCClass_create(neato_parcel, NULL, "Foo", NULL, NULL, NULL, NULL,
+                          NULL, false, false);
+    CFCClass *class_list[2] = { foo_class, NULL };
     CFCType *foo = CFCType_new_object(0, NULL, "Foo", 1);
+    CFCType_resolve(foo, class_list);
 
     {
         CFCType *another_foo = CFCType_new_object(0, NULL, "Foo", 1);
+        CFCType_resolve(another_foo, class_list);
         OK(test, CFCType_equals(foo, another_foo), "equals");
         CFCBase_decref((CFCBase*)another_foo);
     }
@@ -335,13 +357,18 @@ S_run_object_tests(CFCTest *test) {
 
     {
         CFCParcel *foreign_parcel = CFCParcel_new("Foreign", NULL, NULL);
-        CFCParcel_register(foreign_parcel);
+        CFCClass *foreign_foo_class
+            = CFCClass_create(foreign_parcel, NULL, "Foo", NULL, NULL, NULL,
+                              NULL, NULL, false, false);
+        CFCClass *foreign_class_list[2] = { foreign_foo_class, NULL };
         CFCType *foreign_foo = CFCType_new_object(0, foreign_parcel, "Foo", 1);
+        CFCType_resolve(foreign_foo, foreign_class_list);
         OK(test, !CFCType_equals(foo, foreign_foo),
            "different parcel spoils equals");
         STR_EQ(test, CFCType_get_specifier(foreign_foo), "foreign_Foo",
                "prepend parcel prefix to specifier");
         CFCBase_decref((CFCBase*)foreign_parcel);
+        CFCBase_decref((CFCBase*)foreign_foo_class);
         CFCBase_decref((CFCBase*)foreign_foo);
     }
 
@@ -366,8 +393,11 @@ S_run_object_tests(CFCTest *test) {
         CFCBase_decref((CFCBase*)string_type);
     }
 
+    CFCBase_decref((CFCBase*)neato_parcel);
+    CFCBase_decref((CFCBase*)foo_class);
     CFCBase_decref((CFCBase*)foo);
 
+    CFCClass_clear_registry();
     CFCParcel_reap_singletons();
 }
 
@@ -485,7 +515,9 @@ S_run_composite_tests(CFCTest *test) {
     }
 
     {
+        CFCClass *class_list[1] = { NULL };
         CFCType *foo_array = CFCTest_parse_type(test, parser, "foo_t[]");
+        CFCType_resolve(foo_array, class_list);
         STR_EQ(test, CFCType_get_array(foo_array), "[]", "get_array");
         STR_EQ(test, CFCType_to_c(foo_array), "foo_t",
                "array subscripts not included by to_c");

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCTestVariable.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestVariable.c b/clownfish/compiler/src/CFCTestVariable.c
index fd7f291..f0cbcac 100644
--- a/clownfish/compiler/src/CFCTestVariable.c
+++ b/clownfish/compiler/src/CFCTestVariable.c
@@ -16,6 +16,7 @@
 
 #define CFC_USE_TEST_MACROS
 #include "CFCBase.h"
+#include "CFCClass.h"
 #include "CFCParcel.h"
 #include "CFCParser.h"
 #include "CFCSymbol.h"
@@ -28,7 +29,7 @@ S_run_tests(CFCTest *test);
 
 const CFCTestBatch CFCTEST_BATCH_VARIABLE = {
     "Clownfish::CFC::Model::Variable",
-    27,
+    29,
     S_run_tests
 };
 
@@ -37,11 +38,14 @@ S_run_tests(CFCTest *test) {
     CFCParser *parser = CFCParser_new();
     CFCParcel *neato_parcel
         = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+    CFCClass *foo_class = CFCTest_parse_class(test, parser, "class Foo {}");
+    CFCClass *class_list[2] = { foo_class, NULL };
 
     {
         CFCType *type = CFCTest_parse_type(test, parser, "float*");
         CFCVariable *var
             = CFCVariable_new(NULL, NULL, NULL, NULL, "foo", type, 0);
+        CFCVariable_resolve_type(var, class_list);
         STR_EQ(test, CFCVariable_local_c(var), "float* foo", "local_c");
         STR_EQ(test, CFCVariable_local_declaration(var), "float* foo;",
                "local_declaration");
@@ -55,6 +59,7 @@ S_run_tests(CFCTest *test) {
         CFCType *type = CFCTest_parse_type(test, parser, "float[1]");
         CFCVariable *var
             = CFCVariable_new(NULL, NULL, NULL, NULL, "foo", type, 0);
+        CFCVariable_resolve_type(var, class_list);
         STR_EQ(test, CFCVariable_local_c(var), "float foo[1]",
                "to_c appends array to var name rather than type specifier");
 
@@ -68,6 +73,7 @@ S_run_tests(CFCTest *test) {
             = CFCVariable_new(neato_parcel, NULL,
                               "Crustacean::Lobster::LobsterClaw", "LobClaw",
                               "foo", type, 0);
+        CFCVariable_resolve_type(var, class_list);
         STR_EQ(test, CFCVariable_global_c(var), "neato_Foo* neato_LobClaw_foo",
                "global_c");
 
@@ -94,7 +100,9 @@ S_run_tests(CFCTest *test) {
 
     CFCBase_decref((CFCBase*)parser);
     CFCBase_decref((CFCBase*)neato_parcel);
+    CFCBase_decref((CFCBase*)foo_class);
 
+    CFCClass_clear_registry();
     CFCParcel_reap_singletons();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCType.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCType.c b/clownfish/compiler/src/CFCType.c
index 549dff1..0494f93 100644
--- a/clownfish/compiler/src/CFCType.c
+++ b/clownfish/compiler/src/CFCType.c
@@ -26,6 +26,7 @@
 #define CFC_NEED_BASE_STRUCT_DEF
 #include "CFCBase.h"
 #include "CFCType.h"
+#include "CFCClass.h"
 #include "CFCParcel.h"
 #include "CFCSymbol.h"
 #include "CFCUtil.h"
@@ -92,15 +93,8 @@ CFCType_init(CFCType *self, int flags, struct CFCParcel *parcel,
     self->width       = 0;
     self->array       = NULL;
     self->child       = NULL;
-    if (flags & CFCTYPE_OBJECT) {
-        self->vtable_var = CFCUtil_strdup(specifier);
-        for (int i = 0; self->vtable_var[i] != 0; i++) {
-            self->vtable_var[i] = toupper(self->vtable_var[i]);
-        }
-    }
-    else {
-        self->vtable_var  = NULL;
-    }
+    self->vtable_var  = NULL;
+
     return self;
 }
 
@@ -216,14 +210,8 @@ CFCType_new_object(int flags, CFCParcel *parcel, const char *specifier,
         flags |= CFCTYPE_STRING_TYPE;
     }
 
-    char full_specifier[MAX_SPECIFIER_LEN + 1];
     char small_specifier[MAX_SPECIFIER_LEN + 1];
     if (isupper(*specifier)) {
-        const char *prefix = CFCParcel_get_prefix(parcel);
-        if (strlen(prefix) + strlen(specifier) > MAX_SPECIFIER_LEN) {
-            CFCUtil_die("Specifier and/or parcel prefix too long");
-        }
-        sprintf(full_specifier, "%s%s", prefix, specifier);
         strcpy(small_specifier, specifier);
     }
     else if (!isalpha(*specifier)) {
@@ -243,7 +231,6 @@ CFCType_new_object(int flags, CFCParcel *parcel, const char *specifier,
             }
             probe++;
         }
-        strcpy(full_specifier, specifier);
         strcpy(small_specifier, probe);
     }
 
@@ -251,15 +238,6 @@ CFCType_new_object(int flags, CFCParcel *parcel, const char *specifier,
         CFCUtil_die("Invalid specifier: '%s'", specifier);
     }
 
-    // Cache C representation.
-    char c_string[MAX_SPECIFIER_LEN + 10];
-    if (flags & CFCTYPE_CONST) {
-        sprintf(c_string, "const %s*", full_specifier);
-    }
-    else {
-        sprintf(c_string, "%s*", full_specifier);
-    }
-
     int acceptable_flags = CFCTYPE_OBJECT
                            | CFCTYPE_STRING_TYPE
                            | CFCTYPE_CONST
@@ -268,7 +246,7 @@ CFCType_new_object(int flags, CFCParcel *parcel, const char *specifier,
                            | CFCTYPE_DECREMENTED;
     S_check_flags(flags, acceptable_flags, "Object");
 
-    return CFCType_new(flags, parcel, full_specifier, 1, c_string);
+    return CFCType_new(flags, parcel, specifier, 1, NULL);
 }
 
 #define MAX_COMPOSITE_LEN 256
@@ -282,22 +260,8 @@ CFCType_new_composite(int flags, CFCType *child, int indirection,
     flags |= CFCTYPE_COMPOSITE;
     S_check_flags(flags, CFCTYPE_COMPOSITE | CFCTYPE_NULLABLE, "Composite");
 
-    // Cache C representation.
-    // NOTE: Array postfixes are NOT included.
-    const char   *child_c_string = CFCType_to_c(child);
-    size_t        child_c_len    = strlen(child_c_string);
-    size_t        amount         = child_c_len + indirection;
-    if (amount > MAX_COMPOSITE_LEN) {
-        CFCUtil_die("C representation too long");
-    }
-    char c_string[MAX_COMPOSITE_LEN + 1];
-    strcpy(c_string, child_c_string);
-    for (int i = 0; i < indirection; i++) {
-        strncat(c_string, "*", 1);
-    }
-
     CFCType *self = CFCType_new(flags, NULL, CFCType_get_specifier(child),
-                                indirection, c_string);
+                                indirection, NULL);
     self->child = (CFCType*)CFCBase_incref((CFCBase*)child);
 
     // Record array spec.
@@ -335,6 +299,83 @@ CFCType_new_arbitrary(CFCParcel *parcel, const char *specifier) {
 }
 
 void
+CFCType_resolve(CFCType *self, CFCClass **classes) {
+    if (CFCType_is_composite(self)) {
+        CFCType_resolve(self->child, classes);
+
+        // Cache C representation.
+        // NOTE: Array postfixes are NOT included.
+        const char   *child_c_string = CFCType_to_c(self->child);
+        size_t        child_c_len    = strlen(child_c_string);
+        size_t        amount         = child_c_len + self->indirection;
+        if (amount > MAX_COMPOSITE_LEN) {
+            CFCUtil_die("C representation too long");
+        }
+        char c_string[MAX_COMPOSITE_LEN + 1];
+        strcpy(c_string, child_c_string);
+        for (int i = 0; i < self->indirection; i++) {
+            strncat(c_string, "*", 1);
+        }
+        FREEMEM(self->c_string);
+        self->c_string = CFCUtil_strdup(c_string);
+
+        return;
+    }
+    if (!CFCType_is_object(self)) {
+        return;
+    }
+
+    if (isupper(self->specifier[0])) {
+        // Try to find class from class list.
+        const char *specifier = self->specifier;
+        CFCClass   *klass     = NULL;
+
+        for (size_t i = 0; classes[i]; ++i) {
+            CFCClass   *maybe_class = classes[i];
+            const char *struct_sym  = CFCClass_get_struct_sym(maybe_class);
+
+            if (strcmp(specifier, struct_sym) == 0) {
+                if (klass) {
+                    CFCUtil_die("Type '%s' is ambigious", specifier);
+                }
+                klass = maybe_class;
+            }
+        }
+
+        if (!klass) {
+            CFCUtil_die("No class found for type '%s'", specifier);
+        }
+
+        // Create actual specifier with prefix.
+        const char *prefix = CFCClass_get_prefix(klass);
+        if (strlen(prefix) + strlen(specifier) > MAX_SPECIFIER_LEN) {
+            CFCUtil_die("Specifier and/or parcel prefix too long");
+        }
+        char full_specifier[MAX_SPECIFIER_LEN + 1];
+        sprintf(full_specifier, "%s%s", prefix, specifier);
+        FREEMEM(self->specifier);
+        self->specifier = CFCUtil_strdup(full_specifier);
+    }
+
+    // Cache C representation.
+    char c_string[MAX_SPECIFIER_LEN + 10];
+    if (CFCType_const(self)) {
+        sprintf(c_string, "const %s*", self->specifier);
+    }
+    else {
+        sprintf(c_string, "%s*", self->specifier);
+    }
+    FREEMEM(self->c_string);
+    self->c_string = CFCUtil_strdup(c_string);
+
+    // Cache name of VTable variable.
+    self->vtable_var = CFCUtil_strdup(self->specifier);
+    for (int i = 0; self->vtable_var[i] != 0; i++) {
+        self->vtable_var[i] = toupper(self->vtable_var[i]);
+    }
+}
+
+void
 CFCType_destroy(CFCType *self) {
     if (self->child) {
         CFCBase_decref((CFCBase*)self->child);

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCType.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCType.h b/clownfish/compiler/src/CFCType.h
index 5c1354b..937ae94 100644
--- a/clownfish/compiler/src/CFCType.h
+++ b/clownfish/compiler/src/CFCType.h
@@ -25,6 +25,7 @@ extern "C" {
 #endif
 
 typedef struct CFCType CFCType;
+struct CFCClass;
 struct CFCParcel;
 
 #define CFCTYPE_CONST       0x00000001
@@ -173,6 +174,11 @@ CFCType_new_va_list(void);
 CFCType*
 CFCType_new_arbitrary(struct CFCParcel *parcel, const char *specifier);
 
+/** Find the actual class of an object variable without prefix.
+ */
+void
+CFCType_resolve(CFCType *self, struct CFCClass **classes);
+
 void
 CFCType_destroy(CFCType *self);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCVariable.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCVariable.c b/clownfish/compiler/src/CFCVariable.c
index adf743b..54c2a17 100644
--- a/clownfish/compiler/src/CFCVariable.c
+++ b/clownfish/compiler/src/CFCVariable.c
@@ -74,18 +74,30 @@ CFCVariable_init(CFCVariable *self, struct CFCParcel *parcel,
     self->type = (CFCType*)CFCBase_incref((CFCBase*)type);
     self->inert = !!inert;
 
-    // Cache various C string representations.
+    self->local_c   = NULL;
+    self->local_dec = NULL;
+    self->global_c  = NULL;
+
+    return self;
+}
+
+// Cache various C string representations. Will be called after type has
+// been resolved.
+void
+CFCVariable_resolve_type(CFCVariable *self, struct CFCClass **classes) {
+    CFCType *type = self->type;
+    CFCType_resolve(type, classes);
+
     const char *type_str = CFCType_to_c(type);
     const char *postfix  = "";
     if (CFCType_is_composite(type) && CFCType_get_array(type) != NULL) {
         postfix = CFCType_get_array(type);
     }
+    const char *micro_sym = CFCVariable_micro_sym(self);
     self->local_c = CFCUtil_sprintf("%s %s%s", type_str, micro_sym, postfix);
     self->local_dec = CFCUtil_sprintf("%s;", self->local_c);
     const char *full_sym = CFCVariable_full_sym(self);
     self->global_c = CFCUtil_sprintf("%s %s%s", type_str, full_sym, postfix);
-
-    return self;
 }
 
 void

http://git-wip-us.apache.org/repos/asf/lucy/blob/fa4918d2/clownfish/compiler/src/CFCVariable.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCVariable.h b/clownfish/compiler/src/CFCVariable.h
index 2d3fcfc..7263de7 100644
--- a/clownfish/compiler/src/CFCVariable.h
+++ b/clownfish/compiler/src/CFCVariable.h
@@ -34,6 +34,7 @@ extern "C" {
 #endif
 
 typedef struct CFCVariable CFCVariable;
+struct CFCClass;
 struct CFCParcel;
 struct CFCType;
 
@@ -56,6 +57,9 @@ CFCVariable_init(CFCVariable *self, struct CFCParcel *parcel,
                  struct CFCType *type, int inert);
 
 void
+CFCVariable_resolve_type(CFCVariable *self, struct CFCClass **classes);
+
+void
 CFCVariable_destroy(CFCVariable *self);
 
 int


[lucy-commits] [04/26] git commit: refs/heads/separate-clownfish-wip2 - Intra-parcel dependencies

Posted by nw...@apache.org.
Intra-parcel dependencies

Parcels depend on other parcels if:

* A class inherits a class from another parcel.
* A class uses types from another parcel.

This commit makes CFC track these dependencies.

TODO: Perl bindings


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/cbda25ee
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/cbda25ee
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/cbda25ee

Branch: refs/heads/separate-clownfish-wip2
Commit: cbda25ee9c765d1386a8a670770524f1d3fa84de
Parents: 577de07
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun May 26 13:09:14 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:17 2013 +0200

----------------------------------------------------------------------
 clownfish/compiler/src/CFCClass.c  |    5 ++
 clownfish/compiler/src/CFCParcel.c |   89 +++++++++++++++++++++++++++++++
 clownfish/compiler/src/CFCParcel.h |   23 ++++++++
 clownfish/compiler/src/CFCType.c   |   24 ++++++++-
 4 files changed, 139 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/cbda25ee/clownfish/compiler/src/CFCClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCClass.c b/clownfish/compiler/src/CFCClass.c
index 0567ca4..aafaf35 100644
--- a/clownfish/compiler/src/CFCClass.c
+++ b/clownfish/compiler/src/CFCClass.c
@@ -323,6 +323,11 @@ CFCClass_add_child(CFCClass *self, CFCClass *child) {
     self->children[self->num_kids - 1]
         = (CFCClass*)CFCBase_incref((CFCBase*)child);
     self->children[self->num_kids] = NULL;
+
+    // Add parcel dependency.
+    CFCParcel *parcel       = CFCClass_get_parcel(self);
+    CFCParcel *child_parcel = CFCClass_get_parcel(child);
+    CFCParcel_add_inherited_parcel(child_parcel, parcel);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/lucy/blob/cbda25ee/clownfish/compiler/src/CFCParcel.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParcel.c b/clownfish/compiler/src/CFCParcel.c
index f628f66..de2c3bc 100644
--- a/clownfish/compiler/src/CFCParcel.c
+++ b/clownfish/compiler/src/CFCParcel.c
@@ -38,6 +38,10 @@ struct CFCParcel {
     char *Prefix;
     char *PREFIX;
     int is_included;
+    char **dependent_parcels;
+    size_t num_dependent_parcels;
+    char **inherited_parcels;
+    size_t num_inherited_parcels;
 };
 
 static CFCParcel *default_parcel = NULL;
@@ -216,6 +220,12 @@ CFCParcel_init(CFCParcel *self, const char *name, const char *cnick,
     // Set is_included.
     self->is_included = is_included;
 
+    // Initialize dependencies.
+    self->dependent_parcels = (char**)CALLOCATE(1, sizeof(char*));
+    self->num_dependent_parcels = 0;
+    self->inherited_parcels = (char**)CALLOCATE(1, sizeof(char*));
+    self->num_inherited_parcels = 0;
+
     return self;
 }
 
@@ -304,6 +314,14 @@ CFCParcel_destroy(CFCParcel *self) {
     FREEMEM(self->prefix);
     FREEMEM(self->Prefix);
     FREEMEM(self->PREFIX);
+    for (size_t i = 0; self->dependent_parcels[i]; ++i) {
+        FREEMEM(self->dependent_parcels[i]);
+    }
+    FREEMEM(self->dependent_parcels);
+    for (size_t i = 0; self->inherited_parcels[i]; ++i) {
+        FREEMEM(self->inherited_parcels[i]);
+    }
+    FREEMEM(self->inherited_parcels);
     CFCBase_destroy((CFCBase*)self);
 }
 
@@ -361,6 +379,77 @@ CFCParcel_included(CFCParcel *self) {
     return self->is_included;
 }
 
+void
+CFCParcel_add_dependent_parcel(CFCParcel *self, CFCParcel *dependent) {
+    const char *name     = CFCParcel_get_name(self);
+    const char *dep_name = CFCParcel_get_name(dependent);
+
+    if (strcmp(name, dep_name) == 0) { return; }
+
+    for (size_t i = 0; self->dependent_parcels[i]; ++i) {
+        const char *other_name = self->dependent_parcels[i];
+        if (strcmp(other_name, dep_name) == 0) { return; }
+    }
+
+    size_t num_parcels = self->num_dependent_parcels;
+    self->dependent_parcels
+        = (char**)REALLOCATE(self->dependent_parcels,
+                             (num_parcels + 2) * sizeof(char*));
+    self->dependent_parcels[num_parcels]   = CFCUtil_strdup(dep_name);
+    self->dependent_parcels[num_parcels+1] = NULL;
+    self->num_dependent_parcels = num_parcels + 1;
+}
+
+void
+CFCParcel_add_inherited_parcel(CFCParcel *self, CFCParcel *inherited) {
+    const char *name     = CFCParcel_get_name(self);
+    const char *inh_name = CFCParcel_get_name(inherited);
+
+    if (strcmp(name, inh_name) == 0) { return; }
+
+    for (size_t i = 0; self->inherited_parcels[i]; ++i) {
+        const char *other_name = self->inherited_parcels[i];
+        if (strcmp(other_name, inh_name) == 0) { return; }
+    }
+
+    size_t num_parcels = self->num_inherited_parcels;
+    self->inherited_parcels
+        = (char**)REALLOCATE(self->inherited_parcels,
+                             (num_parcels + 2) * sizeof(char*));
+    self->inherited_parcels[num_parcels]   = CFCUtil_strdup(inh_name);
+    self->inherited_parcels[num_parcels+1] = NULL;
+    self->num_inherited_parcels = num_parcels + 1;
+
+    // Add to dependent parcels.
+    CFCParcel_add_dependent_parcel(self, inherited);
+}
+
+CFCParcel**
+CFCParcel_dependent_parcels(CFCParcel *self) {
+    CFCParcel **parcels
+        = (CFCParcel**)CALLOCATE(self->num_dependent_parcels + 1,
+                                 sizeof(CFCParcel*));
+
+    for (size_t i = 0; self->dependent_parcels[i]; ++i) {
+        parcels[i] = CFCParcel_fetch(self->dependent_parcels[i]);
+    }
+
+    return parcels;
+}
+
+CFCParcel**
+CFCParcel_inherited_parcels(CFCParcel *self) {
+    CFCParcel **parcels
+        = (CFCParcel**)CALLOCATE(self->num_inherited_parcels + 1,
+                                 sizeof(CFCParcel*));
+
+    for (size_t i = 0; self->inherited_parcels[i]; ++i) {
+        parcels[i] = CFCParcel_fetch(self->inherited_parcels[i]);
+    }
+
+    return parcels;
+}
+
 /*****************************************************************************
  * The hack JSON parser coded up below is only meant to parse Clownfish parcel
  * file content.  It is limited in its capabilities because so little is legal

http://git-wip-us.apache.org/repos/asf/lucy/blob/cbda25ee/clownfish/compiler/src/CFCParcel.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParcel.h b/clownfish/compiler/src/CFCParcel.h
index e77e5a8..c269fe0 100644
--- a/clownfish/compiler/src/CFCParcel.h
+++ b/clownfish/compiler/src/CFCParcel.h
@@ -115,6 +115,29 @@ CFCParcel_get_PREFIX(CFCParcel *self);
 int
 CFCParcel_included(CFCParcel *self);
 
+/** Add another Parcel that the Parcel depends on.
+ */
+void
+CFCParcel_add_dependent_parcel(CFCParcel *self, CFCParcel *dependent);
+
+/** Add another Parcel containing superclasses that subclasses in the Parcel
+ * extend. Also adds the other Parcel to the Parcel's dependencies.
+ */
+void
+CFCParcel_add_inherited_parcel(CFCParcel *self, CFCParcel *inherited);
+
+/** Return a NULL-terminated array of all Parcels that the Parcel depends on.
+ * Must be freed by the caller.
+ */
+CFCParcel**
+CFCParcel_dependent_parcels(CFCParcel *self);
+
+/** Return a NULL-terminated array of all Parcels containing superclasses that
+ * subclasses in the Parcel extend. Must be freed by the caller.
+ */
+CFCParcel**
+CFCParcel_inherited_parcels(CFCParcel *self);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/lucy/blob/cbda25ee/clownfish/compiler/src/CFCType.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCType.c b/clownfish/compiler/src/CFCType.c
index 0494f93..d0b68ec 100644
--- a/clownfish/compiler/src/CFCType.c
+++ b/clownfish/compiler/src/CFCType.c
@@ -325,11 +325,11 @@ CFCType_resolve(CFCType *self, CFCClass **classes) {
         return;
     }
 
+    CFCClass *klass = NULL;
+
     if (isupper(self->specifier[0])) {
         // Try to find class from class list.
         const char *specifier = self->specifier;
-        CFCClass   *klass     = NULL;
-
         for (size_t i = 0; classes[i]; ++i) {
             CFCClass   *maybe_class = classes[i];
             const char *struct_sym  = CFCClass_get_struct_sym(maybe_class);
@@ -356,6 +356,26 @@ CFCType_resolve(CFCType *self, CFCClass **classes) {
         FREEMEM(self->specifier);
         self->specifier = CFCUtil_strdup(full_specifier);
     }
+    else {
+        // Try to find class from class list.
+        const char *specifier = self->specifier;
+        for (size_t i = 0; classes[i]; ++i) {
+            CFCClass *maybe_class = classes[i];
+            const char *full_struct_sym
+                = CFCClass_full_struct_sym(maybe_class);
+
+            if (strcmp(specifier, full_struct_sym) == 0) {
+                klass = maybe_class;
+                break;
+            }
+        }
+    }
+
+    // Add parcel dependency.
+    if (klass) {
+        CFCParcel *class_parcel = CFCClass_get_parcel(klass);
+        CFCParcel_add_dependent_parcel(self->parcel, class_parcel);
+    }
 
     // Cache C representation.
     char c_string[MAX_SPECIFIER_LEN + 10];


[lucy-commits] [06/26] Move Clownfish runtime tests to a separate parcel

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Util/TestStringHelper.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestStringHelper.c b/core/Lucy/Test/Util/TestStringHelper.c
deleted file mode 100644
index 04a5ba9..0000000
--- a/core/Lucy/Test/Util/TestStringHelper.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Lucy/Util/ToolSet.h"
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/Util/TestStringHelper.h"
-#include "Lucy/Test/TestUtils.h"
-#include "Clownfish/Util/StringHelper.h"
-#include "utf8proc.h"
-#include "Lucy/Util/Json.h"
-
-/* This alternative implementation of utf8_valid() is (presumably) slower, but
- * it implements the standard in a more linear, easy-to-grok way.
- */
-#define TRAIL_OK(n) (n >= 0x80 && n <= 0xBF)
-TestStringHelper*
-TestStrHelp_new(TestFormatter *formatter) {
-    TestStringHelper *self = (TestStringHelper*)VTable_Make_Obj(TESTSTRINGHELPER);
-    return TestStrHelp_init(self, formatter);
-}
-
-TestStringHelper*
-TestStrHelp_init(TestStringHelper *self, TestFormatter *formatter) {
-    return (TestStringHelper*)TestBatch_init((TestBatch*)self, 41, formatter);
-}
-
-static bool
-S_utf8_valid_alt(const char *maybe_utf8, size_t size) {
-    const uint8_t *string = (const uint8_t*)maybe_utf8;
-    const uint8_t *const end = string + size;
-    while (string < end) {
-        int count = StrHelp_UTF8_COUNT[*string];
-        bool valid = false;
-        if (count == 1) {
-            if (string[0] <= 0x7F) {
-                valid = true;
-            }
-        }
-        else if (count == 2) {
-            if (string[0] >= 0xC2 && string[0] <= 0xDF) {
-                if (TRAIL_OK(string[1])) {
-                    valid = true;
-                }
-            }
-        }
-        else if (count == 3) {
-            if (string[0] == 0xE0) {
-                if (string[1] >= 0xA0 && string[1] <= 0xBF
-                    && TRAIL_OK(string[2])
-                   ) {
-                    valid = true;
-                }
-            }
-            else if (string[0] >= 0xE1 && string[0] <= 0xEC) {
-                if (TRAIL_OK(string[1])
-                    && TRAIL_OK(string[2])
-                   ) {
-                    valid = true;
-                }
-            }
-            else if (string[0] == 0xED) {
-                if (string[1] >= 0x80 && string[1] <= 0x9F
-                    && TRAIL_OK(string[2])
-                   ) {
-                    valid = true;
-                }
-            }
-            else if (string[0] >= 0xEE && string[0] <= 0xEF) {
-                if (TRAIL_OK(string[1])
-                    && TRAIL_OK(string[2])
-                   ) {
-                    valid = true;
-                }
-            }
-        }
-        else if (count == 4) {
-            if (string[0] == 0xF0) {
-                if (string[1] >= 0x90 && string[1] <= 0xBF
-                    && TRAIL_OK(string[2])
-                    && TRAIL_OK(string[3])
-                   ) {
-                    valid = true;
-                }
-            }
-            else if (string[0] >= 0xF1 && string[0] <= 0xF3) {
-                if (TRAIL_OK(string[1])
-                    && TRAIL_OK(string[2])
-                    && TRAIL_OK(string[3])
-                   ) {
-                    valid = true;
-                }
-            }
-            else if (string[0] == 0xF4) {
-                if (string[1] >= 0x80 && string[1] <= 0x8F
-                    && TRAIL_OK(string[2])
-                    && TRAIL_OK(string[3])
-                   ) {
-                    valid = true;
-                }
-            }
-        }
-
-        if (!valid) {
-            return false;
-        }
-        string += count;
-    }
-
-    if (string != end) {
-        return false;
-    }
-
-    return true;
-}
-
-static void
-test_overlap(TestBatch *batch) {
-    int32_t result;
-    result = StrHelp_overlap("", "", 0, 0);
-    TEST_INT_EQ(batch, result, 0, "two empty strings");
-    result = StrHelp_overlap("", "foo", 0, 3);
-    TEST_INT_EQ(batch, result, 0, "first string is empty");
-    result = StrHelp_overlap("foo", "", 3, 0);
-    TEST_INT_EQ(batch, result, 0, "second string is empty");
-    result = StrHelp_overlap("foo", "foo", 3, 3);
-    TEST_INT_EQ(batch, result, 3, "equal strings");
-    result = StrHelp_overlap("foo bar", "foo", 7, 3);
-    TEST_INT_EQ(batch, result, 3, "first string is longer");
-    result = StrHelp_overlap("foo", "foo bar", 3, 7);
-    TEST_INT_EQ(batch, result, 3, "second string is longer");
-}
-
-
-static void
-test_to_base36(TestBatch *batch) {
-    char buffer[StrHelp_MAX_BASE36_BYTES];
-    StrHelp_to_base36(UINT64_MAX, buffer);
-    TEST_STR_EQ(batch, "3w5e11264sgsf", buffer, "base36 UINT64_MAX");
-    StrHelp_to_base36(1, buffer);
-    TEST_STR_EQ(batch, "1", buffer, "base36 1");
-    TEST_INT_EQ(batch, buffer[1], 0, "base36 NULL termination");
-}
-
-static void
-test_utf8_round_trip(TestBatch *batch) {
-    uint32_t code_point;
-    for (code_point = 0; code_point <= 0x10FFFF; code_point++) {
-        char buffer[4];
-        uint32_t size = StrHelp_encode_utf8_char(code_point, buffer);
-        char *start = buffer;
-        char *end   = start + size;
-
-        // Verify length returned by encode_utf8_char().
-        if (size != StrHelp_UTF8_COUNT[(unsigned char)buffer[0]]) {
-            break;
-        }
-        // Verify that utf8_valid() agrees with alternate implementation.
-        if (!!StrHelp_utf8_valid(start, size)
-            != !!S_utf8_valid_alt(start, size)
-           ) {
-            break;
-        }
-
-        // Verify back_utf8_char().
-        if (StrHelp_back_utf8_char(end, start) != start) {
-            break;
-        }
-
-        // Verify round trip of encode/decode.
-        if (StrHelp_decode_utf8_char(buffer) != code_point) {
-            break;
-        }
-    }
-    if (code_point == 0x110000) {
-        PASS(batch, "Successfully round tripped 0 - 0x10FFFF");
-    }
-    else {
-        FAIL(batch, "Failed round trip at 0x%.1X", (unsigned)code_point);
-    }
-}
-
-static void
-S_test_validity(TestBatch *batch, const char *content, size_t size,
-                bool expected, const char *description) {
-    bool sane = StrHelp_utf8_valid(content, size);
-    bool double_check = S_utf8_valid_alt(content, size);
-    if (sane != double_check) {
-        FAIL(batch, "Disagreement: %s", description);
-    }
-    else {
-        TEST_TRUE(batch, sane == expected, "%s", description);
-    }
-}
-
-static void
-test_utf8_valid(TestBatch *batch) {
-    // Musical symbol G clef:
-    // Code point: U+1D11E
-    // UTF-16:     0xD834 0xDD1E
-    // UTF-8       0xF0 0x9D 0x84 0x9E
-    S_test_validity(batch, "\xF0\x9D\x84\x9E", 4, true,
-                    "Musical symbol G clef");
-    S_test_validity(batch, "\xED\xA0\xB4\xED\xB4\x9E", 6, false,
-                    "G clef as UTF-8 encoded UTF-16 surrogates");
-    S_test_validity(batch, ".\xED\xA0\xB4.", 5, false,
-                    "Isolated high surrogate");
-    S_test_validity(batch, ".\xED\xB4\x9E.", 5, false,
-                    "Isolated low surrogate");
-
-    // Shortest form.
-    S_test_validity(batch, ".\xC1\x9C.", 4, false,
-                    "Non-shortest form ASCII backslash");
-    S_test_validity(batch, ".\xC0\xAF.", 4, false,
-                    "Non-shortest form ASCII slash");
-    S_test_validity(batch, ".\xC0\x80.", 4, false,
-                    "Non-shortest form ASCII NUL character");
-
-    // Range.
-    S_test_validity(batch, "\xF8\x88\x80\x80\x80", 5, false, "5-byte UTF-8");
-
-    // Bad continuations.
-    S_test_validity(batch, "\xE2\x98\xBA\xE2\x98\xBA", 6, true,
-                    "SmileySmiley");
-    S_test_validity(batch, "\xE2\xBA\xE2\x98\xBA", 5, false,
-                    "missing first continuation byte");
-    S_test_validity(batch, "\xE2\x98\xE2\x98\xBA", 5, false,
-                    "missing second continuation byte");
-    S_test_validity(batch, "\xE2\xE2\x98\xBA", 4, false,
-                    "missing both continuation bytes");
-    S_test_validity(batch, "\xBA\xE2\x98\xBA\xE2\xBA", 5, false,
-                    "missing first continuation byte (end)");
-    S_test_validity(batch, "\xE2\x98\xBA\xE2\x98", 5, false,
-                    "missing second continuation byte (end)");
-    S_test_validity(batch, "\xE2\x98\xBA\xE2", 4, false,
-                    "missing both continuation bytes (end)");
-    S_test_validity(batch, "\xBA\xE2\x98\xBA", 4, false,
-                    "isolated continuation byte 0xBA");
-    S_test_validity(batch, "\x98\xE2\x98\xBA", 4, false,
-                    "isolated continuation byte 0x98");
-    S_test_validity(batch, "\xE2\x98\xBA\xBA", 4, false,
-                    "isolated continuation byte 0xBA (end)");
-    S_test_validity(batch, "\xE2\x98\xBA\x98", 4, false,
-                    "isolated continuation byte 0x98 (end)");
-}
-
-static void
-test_is_whitespace(TestBatch *batch) {
-    TEST_TRUE(batch, StrHelp_is_whitespace(' '), "space is whitespace");
-    TEST_TRUE(batch, StrHelp_is_whitespace('\n'), "newline is whitespace");
-    TEST_TRUE(batch, StrHelp_is_whitespace('\t'), "tab is whitespace");
-    TEST_TRUE(batch, StrHelp_is_whitespace('\v'),
-              "vertical tab is whitespace");
-    TEST_TRUE(batch, StrHelp_is_whitespace(0x180E),
-              "Mongolian vowel separator is whitespace");
-    TEST_FALSE(batch, StrHelp_is_whitespace('a'), "'a' isn't whitespace");
-    TEST_FALSE(batch, StrHelp_is_whitespace(0), "NULL isn't whitespace");
-    TEST_FALSE(batch, StrHelp_is_whitespace(0x263A),
-               "Smiley isn't whitespace");
-}
-
-static void
-test_back_utf8_char(TestBatch *batch) {
-    char buffer[4];
-    char *buf = buffer + 1;
-    uint32_t len = StrHelp_encode_utf8_char(0x263A, buffer);
-    char *end = buffer + len;
-    TEST_TRUE(batch, StrHelp_back_utf8_char(end, buffer) == buffer,
-              "back_utf8_char");
-    TEST_TRUE(batch, StrHelp_back_utf8_char(end, buf) == NULL,
-              "back_utf8_char returns NULL rather than back up beyond start");
-    TEST_TRUE(batch, StrHelp_back_utf8_char(buffer, buffer) == NULL,
-              "back_utf8_char returns NULL when end == start");
-}
-
-static void
-test_utf8proc_normalization(TestBatch *batch) {
-    SKIP(batch, "utf8proc can't handle control chars or Unicode non-chars");
-    return;
-
-    for (int32_t i = 0; i < 100; i++) {
-        CharBuf *source = TestUtils_random_string(rand() % 40);
-
-        // Normalize once.
-        uint8_t *normalized;
-        int32_t check = utf8proc_map(CB_Get_Ptr8(source), CB_Get_Size(source),
-                                     &normalized,
-                                     UTF8PROC_STABLE  |
-                                     UTF8PROC_COMPOSE |
-                                     UTF8PROC_COMPAT  |
-                                     UTF8PROC_CASEFOLD);
-        if (check < 0) {
-            lucy_Json_set_tolerant(1);
-            CharBuf *json = lucy_Json_to_json((Obj*)source);
-            if (!json) {
-                json = CB_newf("[failed to encode]");
-            }
-            FAIL(batch, "Failed to normalize: %s", CB_Get_Ptr8(json));
-            DECREF(json);
-            DECREF(source);
-            return;
-        }
-
-        // Normalize again.
-        size_t normalized_len = strlen((char*)normalized);
-        uint8_t *dupe;
-        int32_t dupe_check = utf8proc_map(normalized, normalized_len, &dupe,
-                                          UTF8PROC_STABLE  |
-                                          UTF8PROC_COMPOSE |
-                                          UTF8PROC_COMPAT  |
-                                          UTF8PROC_CASEFOLD);
-        if (dupe_check < 0) {
-            THROW(ERR, "Unexpected normalization error: %i32", dupe_check);
-        }
-        int comparison = strcmp((char*)normalized, (char*)dupe);
-        free(dupe);
-        free(normalized);
-        DECREF(source);
-        if (comparison != 0) {
-            FAIL(batch, "Not fully normalized");
-            return;
-        }
-    }
-    PASS(batch, "Normalization successful.");
-}
-
-void
-TestStrHelp_run_tests(TestStringHelper *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_overlap(batch);
-    test_to_base36(batch);
-    test_utf8_round_trip(batch);
-    test_utf8_valid(batch);
-    test_is_whitespace(batch);
-    test_back_utf8_char(batch);
-    test_utf8proc_normalization(batch);
-}
-
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Util/TestStringHelper.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestStringHelper.cfh b/core/Lucy/Test/Util/TestStringHelper.cfh
deleted file mode 100644
index d36008c..0000000
--- a/core/Lucy/Test/Util/TestStringHelper.cfh
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Util::TestStringHelper cnick TestStrHelp
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestStringHelper*
-    new(TestFormatter *formatter);
-
-    inert TestStringHelper*
-    init(TestStringHelper *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestStringHelper *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/TestClownfish.c
----------------------------------------------------------------------
diff --git a/core/TestClownfish.c b/core/TestClownfish.c
new file mode 100644
index 0000000..a946163
--- /dev/null
+++ b/core/TestClownfish.c
@@ -0,0 +1,20 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+void
+testcfish_init_parcel() {
+}
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/TestClownfish.cfp
----------------------------------------------------------------------
diff --git a/core/TestClownfish.cfp b/core/TestClownfish.cfp
new file mode 100644
index 0000000..f1c9411
--- /dev/null
+++ b/core/TestClownfish.cfp
@@ -0,0 +1,5 @@
+{
+    "name": "TestClownfish",
+    "nickname": "TestCfish",
+    "version": "v0.3.0"
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/Build.PL
----------------------------------------------------------------------
diff --git a/perl/Build.PL b/perl/Build.PL
index ce003dc..d46e618 100644
--- a/perl/Build.PL
+++ b/perl/Build.PL
@@ -68,7 +68,7 @@ my $builder = Lucy::Build->new(
             $UTF8PROC_SRC_DIR,
         ],
     },
-    extra_compiler_flags => '-DCFP_CFISH -DCFP_LUCY',
+    extra_compiler_flags => '-DCFP_CFISH -DCFP_TESTCFISH -DCFP_LUCY',
     add_to_cleanup => [
         qw(
             Lucy-*

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/buildlib/Lucy/Build/Binding/Misc.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Misc.pm b/perl/buildlib/Lucy/Build/Binding/Misc.pm
index c1377e0..55b372a 100644
--- a/perl/buildlib/Lucy/Build/Binding/Misc.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Misc.pm
@@ -22,7 +22,8 @@ $VERSION = eval $VERSION;
 sub bind_all {
     my $class = shift;
     $class->bind_lucy;
-    $class->bind_test;
+    $class->bind_cfish_test;
+    $class->bind_lucy_test;
     $class->bind_testschema;
     $class->bind_bbsortex;
 }
@@ -77,7 +78,35 @@ END_XS_CODE
     Clownfish::CFC::Binding::Perl::Class->register($binding);
 }
 
-sub bind_test {
+sub bind_cfish_test {
+    my $xs_code = <<'END_XS_CODE';
+MODULE = Lucy   PACKAGE = Clownfish::Test
+
+bool
+run_tests(package)
+    char *package;
+CODE:
+    cfish_CharBuf *class_name = cfish_CB_newf("%s", package);
+    cfish_TestFormatter *formatter
+        = (cfish_TestFormatter*)cfish_TestFormatterTAP_new();
+    bool result = testcfish_Test_run_batch(class_name, formatter);
+    CFISH_DECREF(class_name);
+    CFISH_DECREF(formatter);
+
+    RETVAL = result;
+OUTPUT: RETVAL
+END_XS_CODE
+
+    my $binding = Clownfish::CFC::Binding::Perl::Class->new(
+        parcel     => "TestClownfish",
+        class_name => "Clownfish::Test",
+    );
+    $binding->append_xs($xs_code);
+
+    Clownfish::CFC::Binding::Perl::Class->register($binding);
+}
+
+sub bind_lucy_test {
     my $xs_code = <<'END_XS_CODE';
 MODULE = Lucy   PACKAGE = Lucy::Test
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/lib/Clownfish/Test.pm
----------------------------------------------------------------------
diff --git a/perl/lib/Clownfish/Test.pm b/perl/lib/Clownfish/Test.pm
new file mode 100644
index 0000000..1bd3c79
--- /dev/null
+++ b/perl/lib/Clownfish/Test.pm
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+package Clownfish::Test;
+use Lucy;
+our $VERSION = '0.003000';
+$VERSION = eval $VERSION;
+
+1;
+
+__END__
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/016-varray.t
----------------------------------------------------------------------
diff --git a/perl/t/core/016-varray.t b/perl/t/core/016-varray.t
index 6e214c2..5ddb5c1 100644
--- a/perl/t/core/016-varray.t
+++ b/perl/t/core/016-varray.t
@@ -16,8 +16,8 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Object::TestVArray");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests("Clownfish::Test::TestVArray");
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/017-hash.t
----------------------------------------------------------------------
diff --git a/perl/t/core/017-hash.t b/perl/t/core/017-hash.t
index 36c61ec..f8583c8 100644
--- a/perl/t/core/017-hash.t
+++ b/perl/t/core/017-hash.t
@@ -16,8 +16,8 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Object::TestHash");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests("Clownfish::Test::TestHash");
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/019-obj.t
----------------------------------------------------------------------
diff --git a/perl/t/core/019-obj.t b/perl/t/core/019-obj.t
index 470c8c7..ea51ecf 100644
--- a/perl/t/core/019-obj.t
+++ b/perl/t/core/019-obj.t
@@ -16,8 +16,8 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Object::TestObj");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests("Clownfish::Test::TestObj");
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/020-err.t
----------------------------------------------------------------------
diff --git a/perl/t/core/020-err.t b/perl/t/core/020-err.t
index 2a9ccf1..0679130 100644
--- a/perl/t/core/020-err.t
+++ b/perl/t/core/020-err.t
@@ -16,8 +16,8 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Object::TestErr");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests("Clownfish::Test::TestErr");
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/022-bytebuf.t
----------------------------------------------------------------------
diff --git a/perl/t/core/022-bytebuf.t b/perl/t/core/022-bytebuf.t
index a6de264..5dd7437 100644
--- a/perl/t/core/022-bytebuf.t
+++ b/perl/t/core/022-bytebuf.t
@@ -16,8 +16,8 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Object::TestByteBuf");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests("Clownfish::Test::TestByteBuf");
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/029-charbuf.t
----------------------------------------------------------------------
diff --git a/perl/t/core/029-charbuf.t b/perl/t/core/029-charbuf.t
index 33c28a5..39041fb 100644
--- a/perl/t/core/029-charbuf.t
+++ b/perl/t/core/029-charbuf.t
@@ -16,8 +16,8 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Object::TestCharBuf");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests("Clownfish::Test::TestCharBuf");
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/030-number_utils.t
----------------------------------------------------------------------
diff --git a/perl/t/core/030-number_utils.t b/perl/t/core/030-number_utils.t
index 672f3cd..1035f96 100644
--- a/perl/t/core/030-number_utils.t
+++ b/perl/t/core/030-number_utils.t
@@ -16,8 +16,10 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Util::TestNumberUtils");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests(
+    "Clownfish::Test::Util::TestNumberUtils"
+);
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/031-num.t
----------------------------------------------------------------------
diff --git a/perl/t/core/031-num.t b/perl/t/core/031-num.t
index e1d00fa..e784ae6 100644
--- a/perl/t/core/031-num.t
+++ b/perl/t/core/031-num.t
@@ -16,8 +16,8 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Object::TestNum");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests("Clownfish::Test::TestNum");
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/032-string_helper.t
----------------------------------------------------------------------
diff --git a/perl/t/core/032-string_helper.t b/perl/t/core/032-string_helper.t
index d5e80d1..ffa4fbe 100644
--- a/perl/t/core/032-string_helper.t
+++ b/perl/t/core/032-string_helper.t
@@ -16,8 +16,10 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Util::TestStringHelper");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests(
+    "Clownfish::Test::Util::TestStringHelper"
+);
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/037-atomic.t
----------------------------------------------------------------------
diff --git a/perl/t/core/037-atomic.t b/perl/t/core/037-atomic.t
index c21c0dd..1ed26e9 100644
--- a/perl/t/core/037-atomic.t
+++ b/perl/t/core/037-atomic.t
@@ -16,8 +16,8 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Util::TestAtomic");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests("Clownfish::Test::Util::TestAtomic");
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/038-lock_free_registry.t
----------------------------------------------------------------------
diff --git a/perl/t/core/038-lock_free_registry.t b/perl/t/core/038-lock_free_registry.t
index d9940b5..f6484c6 100644
--- a/perl/t/core/038-lock_free_registry.t
+++ b/perl/t/core/038-lock_free_registry.t
@@ -16,8 +16,10 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Object::TestLockFreeRegistry");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests(
+    "Clownfish::Test::TestLockFreeRegistry"
+);
 
 exit($success ? 0 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/perl/t/core/039-memory.t
----------------------------------------------------------------------
diff --git a/perl/t/core/039-memory.t b/perl/t/core/039-memory.t
index 8bf2565..16c1c68 100644
--- a/perl/t/core/039-memory.t
+++ b/perl/t/core/039-memory.t
@@ -16,8 +16,8 @@
 use strict;
 use warnings;
 
-use Lucy::Test;
-my $success = Lucy::Test::run_tests("Lucy::Test::Util::TestMemory");
+use Clownfish::Test;
+my $success = Clownfish::Test::run_tests("Clownfish::Test::Util::TestMemory");
 
 exit($success ? 0 : 1);
 


[lucy-commits] [17/26] git commit: refs/heads/separate-clownfish-wip2 - Use Clownfish::TestHarness::TestUtils in Lucy tests

Posted by nw...@apache.org.
Use Clownfish::TestHarness::TestUtils in Lucy tests


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/cb138770
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/cb138770
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/cb138770

Branch: refs/heads/separate-clownfish-wip2
Commit: cb13877042f5f6d157ae3b8d89cd82775e192c7f
Parents: d4d7d02
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 27 22:55:09 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:32:00 2013 +0200

----------------------------------------------------------------------
 core/Lucy/Test/Object/TestBitVector.c   |    1 +
 core/Lucy/Test/Search/TestQueryParser.c |    1 +
 core/Lucy/Test/Search/TestSortSpec.c    |    1 +
 core/Lucy/Test/Store/TestIOChunks.c     |    1 +
 core/Lucy/Test/Store/TestIOPrimitives.c |    1 +
 core/Lucy/Test/TestUtils.c              |  108 +-------------------------
 core/Lucy/Test/TestUtils.cfh            |   49 ------------
 7 files changed, 6 insertions(+), 156 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/cb138770/core/Lucy/Test/Object/TestBitVector.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestBitVector.c b/core/Lucy/Test/Object/TestBitVector.c
index cd04fbb..669ae67 100644
--- a/core/Lucy/Test/Object/TestBitVector.c
+++ b/core/Lucy/Test/Object/TestBitVector.c
@@ -19,6 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Object/TestBitVector.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/cb138770/core/Lucy/Test/Search/TestQueryParser.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParser.c b/core/Lucy/Test/Search/TestQueryParser.c
index 665b275..eef20e3 100644
--- a/core/Lucy/Test/Search/TestQueryParser.c
+++ b/core/Lucy/Test/Search/TestQueryParser.c
@@ -19,6 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <string.h>
 
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test/Search/TestQueryParser.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Search/TermQuery.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/cb138770/core/Lucy/Test/Search/TestSortSpec.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSortSpec.c b/core/Lucy/Test/Search/TestSortSpec.c
index e889b0e..9b4dd3b 100644
--- a/core/Lucy/Test/Search/TestSortSpec.c
+++ b/core/Lucy/Test/Search/TestSortSpec.c
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 
 #include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestSortSpec.h"
 #include "Lucy/Test/TestUtils.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/cb138770/core/Lucy/Test/Store/TestIOChunks.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOChunks.c b/core/Lucy/Test/Store/TestIOChunks.c
index cae365c..cbf4f10 100644
--- a/core/Lucy/Test/Store/TestIOChunks.c
+++ b/core/Lucy/Test/Store/TestIOChunks.c
@@ -23,6 +23,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Store/TestIOChunks.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/cb138770/core/Lucy/Test/Store/TestIOPrimitives.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOPrimitives.c b/core/Lucy/Test/Store/TestIOPrimitives.c
index 55e3c78..38635d8 100644
--- a/core/Lucy/Test/Store/TestIOPrimitives.c
+++ b/core/Lucy/Test/Store/TestIOPrimitives.c
@@ -23,6 +23,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Store/TestIOPrimitives.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/cb138770/core/Lucy/Test/TestUtils.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestUtils.c b/core/Lucy/Test/TestUtils.c
index 36f51f4..e345338 100644
--- a/core/Lucy/Test/TestUtils.c
+++ b/core/Lucy/Test/TestUtils.c
@@ -22,6 +22,7 @@
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Analysis/Analyzer.h"
 #include "Lucy/Analysis/Inversion.h"
 #include "Lucy/Analysis/Token.h"
@@ -37,88 +38,6 @@
 #include "Lucy/Store/RAMFile.h"
 #include "Lucy/Util/Freezer.h"
 
-uint64_t
-TestUtils_random_u64() {
-    uint64_t num = ((uint64_t)(rand()   & 0x7FFF) << 60)
-                   | ((uint64_t)(rand() & 0x7FFF) << 45)
-                   | ((uint64_t)(rand() & 0x7FFF) << 30)
-                   | ((uint64_t)(rand() & 0x7FFF) << 15)
-                   | ((uint64_t)(rand() & 0x7FFF) << 0);
-    return num;
-}
-
-int64_t*
-TestUtils_random_i64s(int64_t *buf, size_t count, int64_t min,
-                      int64_t limit) {
-    uint64_t  range = min < limit ? limit - min : 0;
-    int64_t *ints = buf ? buf : (int64_t*)CALLOCATE(count, sizeof(int64_t));
-    for (size_t i = 0; i < count; i++) {
-        ints[i] = min + TestUtils_random_u64() % range;
-    }
-    return ints;
-}
-
-uint64_t*
-TestUtils_random_u64s(uint64_t *buf, size_t count, uint64_t min,
-                      uint64_t limit) {
-    uint64_t  range = min < limit ? limit - min : 0;
-    uint64_t *ints = buf ? buf : (uint64_t*)CALLOCATE(count, sizeof(uint64_t));
-    for (size_t i = 0; i < count; i++) {
-        ints[i] = min + TestUtils_random_u64() % range;
-    }
-    return ints;
-}
-
-double*
-TestUtils_random_f64s(double *buf, size_t count) {
-    double *f64s = buf ? buf : (double*)CALLOCATE(count, sizeof(double));
-    for (size_t i = 0; i < count; i++) {
-        uint64_t num = TestUtils_random_u64();
-        f64s[i] = U64_TO_DOUBLE(num) / UINT64_MAX;
-    }
-    return f64s;
-}
-
-static uint32_t
-S_random_code_point(void) {
-    uint32_t code_point = 0;
-    while (1) {
-        uint8_t chance = (rand() % 9) + 1;
-        switch (chance) {
-            case 1: case 2: case 3:
-                code_point = rand() % 0x80;
-                break;
-            case 4: case 5: case 6:
-                code_point = (rand() % (0x0800  - 0x0080)) + 0x0080;
-                break;
-            case 7: case 8:
-                code_point = (rand() % (0x10000 - 0x0800)) + 0x0800;
-                break;
-            case 9: {
-                    uint64_t num = TestUtils_random_u64();
-                    code_point = (num % (0x10FFFF - 0x10000)) + 0x10000;
-                }
-        }
-        if (code_point > 0x10FFFF) {
-            continue; // Too high.
-        }
-        if (code_point > 0xD7FF && code_point < 0xE000) {
-            continue; // UTF-16 surrogate.
-        }
-        break;
-    }
-    return code_point;
-}
-
-CharBuf*
-TestUtils_random_string(size_t length) {
-    CharBuf *string = CB_new(length);
-    while (length--) {
-        CB_Cat_Char(string, S_random_code_point());
-    }
-    return string;
-}
-
 VArray*
 TestUtils_doc_set() {
     VArray *docs = VA_new(10);
@@ -134,11 +53,6 @@ TestUtils_doc_set() {
     return docs;
 }
 
-CharBuf*
-TestUtils_get_cb(const char *ptr) {
-    return CB_new_from_utf8(ptr, strlen(ptr));
-}
-
 PolyQuery*
 TestUtils_make_poly_query(uint32_t boolop, ...) {
     va_list args;
@@ -212,26 +126,6 @@ TestUtils_make_range_query(const char *field, const char *lower_term,
                           include_upper);
 }
 
-Obj*
-TestUtils_freeze_thaw(Obj *object) {
-    if (object) {
-        RAMFile *ram_file = RAMFile_new(NULL, false);
-        OutStream *outstream = OutStream_open((Obj*)ram_file);
-        FREEZE(object, outstream);
-        OutStream_Close(outstream);
-        DECREF(outstream);
-
-        InStream *instream = InStream_open((Obj*)ram_file);
-        Obj *retval = THAW(instream);
-        DECREF(instream);
-        DECREF(ram_file);
-        return retval;
-    }
-    else {
-        return NULL;
-    }
-}
-
 void
 TestUtils_test_analyzer(TestBatch *batch, Analyzer *analyzer, CharBuf *source,
                         VArray *expected, const char *message) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/cb138770/core/Lucy/Test/TestUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestUtils.cfh b/core/Lucy/Test/TestUtils.cfh
index 23c55c5..189ad0a 100644
--- a/core/Lucy/Test/TestUtils.cfh
+++ b/core/Lucy/Test/TestUtils.cfh
@@ -18,49 +18,6 @@ parcel TestLucy;
 
 inert class Lucy::Test::TestUtils  {
 
-    /** Testing-only CharBuf factory which uses strlen().
-     */
-    inert incremented CharBuf*
-    get_cb(const char *utf8);
-
-    /** Return a random unsigned 64-bit integer.
-     */
-    inert uint64_t
-    random_u64();
-
-    /** Return an array of <code>count</code> random 64-bit integers where
-     * <code>min <= n < limit</code>.
-     *
-     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
-     * be used.
-     */
-    inert int64_t*
-    random_i64s(int64_t *buf, size_t count, int64_t min, int64_t limit);
-
-    /** Return an array of <code>count</code> random unsigned, 64-bit integers
-     * where <code>min <= n < limit</code>.
-     *
-     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
-     * be used.
-     */
-    inert uint64_t*
-    random_u64s(uint64_t *buf, size_t count, uint64_t min, uint64_t limit);
-
-    /** Return an array of <code>count</code> random double-precision floating
-     * point numbers between 0 and 1.
-     *
-     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
-     * be used.
-     */
-    inert double*
-    random_f64s(double *buf, size_t count);
-
-    /** Return a string with a random (legal) sequence of code points.
-     * @param length Length of the string in code points.
-     */
-    inert incremented CharBuf*
-    random_string(size_t length);
-
     /** Return a VArray of CharBufs, each representing the content for a
      * document in the shared collection.
      */
@@ -102,12 +59,6 @@ inert class Lucy::Test::TestUtils  {
     inert incremented PolyQuery*
     make_poly_query(uint32_t boolop, ...);
 
-    /** Return the result of round-tripping the object through FREEZE and
-     * THAW.
-     */
-    inert incremented Obj*
-    freeze_thaw(Obj *object);
-
     /** Verify an Analyzer's transform, transform_text, and split methods.
      */
     inert void


[lucy-commits] [22/26] Rework Clownfish test harness

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestPhraseQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPhraseQuery.cfh b/core/Lucy/Test/Search/TestPhraseQuery.cfh
index d1fcd07..78969dc 100644
--- a/core/Lucy/Test/Search/TestPhraseQuery.cfh
+++ b/core/Lucy/Test/Search/TestPhraseQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestPhraseQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPhraseQuery*
-    new(TestFormatter *formatter);
-
-    inert TestPhraseQuery*
-    init(TestPhraseQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestPhraseQuery *self);
+    Run(TestPhraseQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestPolyQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPolyQuery.c b/core/Lucy/Test/Search/TestPolyQuery.c
index 370f646..88166f7 100644
--- a/core/Lucy/Test/Search/TestPolyQuery.c
+++ b/core/Lucy/Test/Search/TestPolyQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestPolyQuery.h"
@@ -29,29 +29,17 @@
 #include "Lucy/Search/LeafQuery.h"
 
 TestANDQuery*
-TestANDQuery_new(TestFormatter *formatter) {
-    TestANDQuery *self = (TestANDQuery*)VTable_Make_Obj(TESTANDQUERY);
-    return TestANDQuery_init(self, formatter);
-}
-
-TestANDQuery*
-TestANDQuery_init(TestANDQuery *self, TestFormatter *formatter) {
-    return (TestANDQuery*)TestBatch_init((TestBatch*)self, 4, formatter);
-}
-
-TestORQuery*
-TestORQuery_new(TestFormatter *formatter) {
-    TestORQuery *self = (TestORQuery*)VTable_Make_Obj(TESTORQUERY);
-    return TestORQuery_init(self, formatter);
+TestANDQuery_new() {
+    return (TestANDQuery*)VTable_Make_Obj(TESTANDQUERY);
 }
 
 TestORQuery*
-TestORQuery_init(TestORQuery *self, TestFormatter *formatter) {
-    return (TestORQuery*)TestBatch_init((TestBatch*)self, 4, formatter);
+TestORQuery_new() {
+    return (TestORQuery*)VTable_Make_Obj(TESTORQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch, uint32_t boolop) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner, uint32_t boolop) {
     LeafQuery *a_leaf  = TestUtils_make_leaf_query(NULL, "a");
     LeafQuery *b_leaf  = TestUtils_make_leaf_query(NULL, "b");
     LeafQuery *c_leaf  = TestUtils_make_leaf_query(NULL, "c");
@@ -69,14 +57,14 @@ test_Dump_Load_and_Equals(TestBatch *batch, uint32_t boolop) {
     Obj *dump = (Obj*)PolyQuery_Dump(query);
     PolyQuery *clone = (PolyQuery*)Obj_Load(dump, dump);
 
-    TEST_FALSE(batch, PolyQuery_Equals(query, (Obj*)kids_differ),
+    TEST_FALSE(runner, PolyQuery_Equals(query, (Obj*)kids_differ),
                "Different kids spoil Equals");
-    TEST_TRUE(batch, PolyQuery_Equals(query, (Obj*)boost_differs),
+    TEST_TRUE(runner, PolyQuery_Equals(query, (Obj*)boost_differs),
               "Equals with identical boosts");
     PolyQuery_Set_Boost(boost_differs, 1.5);
-    TEST_FALSE(batch, PolyQuery_Equals(query, (Obj*)boost_differs),
+    TEST_FALSE(runner, PolyQuery_Equals(query, (Obj*)boost_differs),
                "Different boost spoils Equals");
-    TEST_TRUE(batch, PolyQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, PolyQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
 
     DECREF(a_leaf);
@@ -90,15 +78,15 @@ test_Dump_Load_and_Equals(TestBatch *batch, uint32_t boolop) {
 }
 
 void
-TestANDQuery_run_tests(TestANDQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch, BOOLOP_AND);
+TestANDQuery_run(TestANDQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+    test_Dump_Load_and_Equals(runner, BOOLOP_AND);
 }
 
 void
-TestORQuery_run_tests(TestORQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch, BOOLOP_OR);
+TestORQuery_run(TestORQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+    test_Dump_Load_and_Equals(runner, BOOLOP_OR);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestPolyQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPolyQuery.cfh b/core/Lucy/Test/Search/TestPolyQuery.cfh
index b509286..3e4a42d 100644
--- a/core/Lucy/Test/Search/TestPolyQuery.cfh
+++ b/core/Lucy/Test/Search/TestPolyQuery.cfh
@@ -20,26 +20,20 @@ class Lucy::Test::Search::TestANDQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestANDQuery*
-    new(TestFormatter *formatter);
-
-    inert TestANDQuery*
-    init(TestANDQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestANDQuery *self);
+    Run(TestANDQuery *self, TestBatchRunner *runner);
 }
 
 class Lucy::Test::Search::TestORQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestORQuery*
-    new(TestFormatter *formatter);
-
-    inert TestORQuery*
-    init(TestORQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestORQuery *self);
+    Run(TestORQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestQueryParserLogic.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserLogic.c b/core/Lucy/Test/Search/TestQueryParserLogic.c
index 5e807a7..57049e5 100644
--- a/core/Lucy/Test/Search/TestQueryParserLogic.c
+++ b/core/Lucy/Test/Search/TestQueryParserLogic.c
@@ -20,7 +20,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <string.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestQueryParserLogic.h"
 #include "Lucy/Test/Search/TestQueryParser.h"
@@ -48,14 +48,8 @@
 #define make_poly_query   (Query*)TestUtils_make_poly_query
 
 TestQueryParserLogic*
-TestQPLogic_new(TestFormatter *formatter) {
-    TestQueryParserLogic *self = (TestQueryParserLogic*)VTable_Make_Obj(TESTQUERYPARSERLOGIC);
-    return TestQPLogic_init(self, formatter);
-}
-
-TestQueryParserLogic*
-TestQPLogic_init(TestQueryParserLogic *self, TestFormatter *formatter) {
-    return (TestQueryParserLogic*)TestBatch_init((TestBatch*)self, 258, formatter);
+TestQPLogic_new() {
+    return (TestQueryParserLogic*)VTable_Make_Obj(TESTQUERYPARSERLOGIC);
 }
 
 static TestQueryParser*
@@ -888,9 +882,10 @@ S_create_index() {
 }
 
 void
-TestQPLogic_run_tests(TestQueryParserLogic *self) {
+TestQPLogic_run(TestQueryParserLogic *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 258);
+
     uint32_t i;
-    TestBatch     *batch      = (TestBatch*)self;
     Folder        *folder     = S_create_index();
     IndexSearcher *searcher   = IxSearcher_new((Obj*)folder);
     QueryParser   *or_parser  = QParser_new(IxSearcher_Get_Schema(searcher),
@@ -909,9 +904,9 @@ TestQPLogic_run_tests(TestQueryParserLogic *self) {
         Query *parsed   = QParser_Parse(or_parser, test_case->query_string);
         Hits  *hits     = IxSearcher_Hits(searcher, (Obj*)parsed, 0, 10, NULL);
 
-        TEST_TRUE(batch, Query_Equals(tree, (Obj*)test_case->tree),
+        TEST_TRUE(runner, Query_Equals(tree, (Obj*)test_case->tree),
                   "tree() OR   %s", (char*)CB_Get_Ptr8(test_case->query_string));
-        TEST_INT_EQ(batch, Hits_Total_Hits(hits), test_case->num_hits,
+        TEST_INT_EQ(runner, Hits_Total_Hits(hits), test_case->num_hits,
                     "hits: OR   %s", (char*)CB_Get_Ptr8(test_case->query_string));
         DECREF(hits);
         DECREF(parsed);
@@ -927,9 +922,9 @@ TestQPLogic_run_tests(TestQueryParserLogic *self) {
         Query *parsed   = QParser_Parse(and_parser, test_case->query_string);
         Hits  *hits     = IxSearcher_Hits(searcher, (Obj*)parsed, 0, 10, NULL);
 
-        TEST_TRUE(batch, Query_Equals(tree, (Obj*)test_case->tree),
+        TEST_TRUE(runner, Query_Equals(tree, (Obj*)test_case->tree),
                   "tree() AND   %s", (char*)CB_Get_Ptr8(test_case->query_string));
-        TEST_INT_EQ(batch, Hits_Total_Hits(hits), test_case->num_hits,
+        TEST_INT_EQ(runner, Hits_Total_Hits(hits), test_case->num_hits,
                     "hits: AND   %s", (char*)CB_Get_Ptr8(test_case->query_string));
         DECREF(hits);
         DECREF(parsed);
@@ -950,11 +945,11 @@ TestQPLogic_run_tests(TestQueryParserLogic *self) {
         Query *expanded;
         Hits  *hits;
 
-        TEST_TRUE(batch, Query_Equals(pruned, (Obj*)wanted),
+        TEST_TRUE(runner, Query_Equals(pruned, (Obj*)wanted),
                   "prune()   %s", (char*)CB_Get_Ptr8(qstring));
         expanded = QParser_Expand(or_parser, pruned);
         hits = IxSearcher_Hits(searcher, (Obj*)expanded, 0, 10, NULL);
-        TEST_INT_EQ(batch, Hits_Total_Hits(hits), test_case->num_hits,
+        TEST_INT_EQ(runner, Hits_Total_Hits(hits), test_case->num_hits,
                     "hits:    %s", (char*)CB_Get_Ptr8(qstring));
 
         DECREF(hits);

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestQueryParserLogic.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserLogic.cfh b/core/Lucy/Test/Search/TestQueryParserLogic.cfh
index 888e1ae..45052b6 100644
--- a/core/Lucy/Test/Search/TestQueryParserLogic.cfh
+++ b/core/Lucy/Test/Search/TestQueryParserLogic.cfh
@@ -23,13 +23,10 @@ class Lucy::Test::Search::TestQueryParserLogic cnick TestQPLogic
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestQueryParserLogic*
-    new(TestFormatter *formatter);
-
-    inert TestQueryParserLogic*
-    init(TestQueryParserLogic *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestQueryParserLogic *self);
+    Run(TestQueryParserLogic *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestQueryParserSyntax.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserSyntax.c b/core/Lucy/Test/Search/TestQueryParserSyntax.c
index 06db2d5..b0baf15 100644
--- a/core/Lucy/Test/Search/TestQueryParserSyntax.c
+++ b/core/Lucy/Test/Search/TestQueryParserSyntax.c
@@ -20,7 +20,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <string.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestQueryParserSyntax.h"
 #include "Lucy/Test/Search/TestQueryParser.h"
@@ -51,15 +51,8 @@
 #define make_poly_query   (Query*)TestUtils_make_poly_query
 
 TestQueryParserSyntax*
-TestQPSyntax_new(TestFormatter *formatter) {
-    TestQueryParserSyntax *self
-        = (TestQueryParserSyntax*)VTable_Make_Obj(TESTQUERYPARSERSYNTAX);
-    return TestQPSyntax_init(self, formatter);
-}
-
-TestQueryParserSyntax*
-TestQPSyntax_init(TestQueryParserSyntax *self, TestFormatter *formatter) {
-    return (TestQueryParserSyntax*)TestBatch_init((TestBatch*)self, 68, formatter);
+TestQPSyntax_new() {
+    return (TestQueryParserSyntax*)VTable_Make_Obj(TESTQUERYPARSERSYNTAX);
 }
 
 static Folder*
@@ -380,17 +373,17 @@ static Lucy_TestQPSyntax_Test_t syntax_test_funcs[] = {
 };
 
 static void
-test_query_parser_syntax(TestBatch *batch) {
+test_query_parser_syntax(TestBatchRunner *runner) {
     if (!RegexTokenizer_is_available()) {
         for (uint32_t i = 0; leaf_test_funcs[i] != NULL; i++) {
-            SKIP(batch, "RegexTokenizer not available");
-            SKIP(batch, "RegexTokenizer not available");
-            SKIP(batch, "RegexTokenizer not available");
+            SKIP(runner, "RegexTokenizer not available");
+            SKIP(runner, "RegexTokenizer not available");
+            SKIP(runner, "RegexTokenizer not available");
         }
 
         for (uint32_t i = 0; syntax_test_funcs[i] != NULL; i++) {
-            SKIP(batch, "RegexTokenizer not available");
-            SKIP(batch, "RegexTokenizer not available");
+            SKIP(runner, "RegexTokenizer not available");
+            SKIP(runner, "RegexTokenizer not available");
         }
 
         return;
@@ -410,11 +403,11 @@ test_query_parser_syntax(TestBatch *batch) {
         Query *parsed   = QParser_Parse(qparser, test_case->query_string);
         Hits  *hits     = IxSearcher_Hits(searcher, (Obj*)parsed, 0, 10, NULL);
 
-        TEST_TRUE(batch, Query_Equals(tree, (Obj*)test_case->tree),
+        TEST_TRUE(runner, Query_Equals(tree, (Obj*)test_case->tree),
                   "tree()    %s", (char*)CB_Get_Ptr8(test_case->query_string));
-        TEST_TRUE(batch, Query_Equals(expanded, (Obj*)test_case->expanded),
+        TEST_TRUE(runner, Query_Equals(expanded, (Obj*)test_case->expanded),
                   "expand_leaf()    %s", (char*)CB_Get_Ptr8(test_case->query_string));
-        TEST_INT_EQ(batch, Hits_Total_Hits(hits), test_case->num_hits,
+        TEST_INT_EQ(runner, Hits_Total_Hits(hits), test_case->num_hits,
                     "hits:    %s", (char*)CB_Get_Ptr8(test_case->query_string));
         DECREF(hits);
         DECREF(parsed);
@@ -430,9 +423,9 @@ test_query_parser_syntax(TestBatch *batch) {
         Query *parsed = QParser_Parse(qparser, test_case->query_string);
         Hits  *hits   = IxSearcher_Hits(searcher, (Obj*)parsed, 0, 10, NULL);
 
-        TEST_TRUE(batch, Query_Equals(tree, (Obj*)test_case->tree),
+        TEST_TRUE(runner, Query_Equals(tree, (Obj*)test_case->tree),
                   "tree()    %s", (char*)CB_Get_Ptr8(test_case->query_string));
-        TEST_INT_EQ(batch, Hits_Total_Hits(hits), test_case->num_hits,
+        TEST_INT_EQ(runner, Hits_Total_Hits(hits), test_case->num_hits,
                     "hits:    %s", (char*)CB_Get_Ptr8(test_case->query_string));
         DECREF(hits);
         DECREF(parsed);
@@ -446,9 +439,9 @@ test_query_parser_syntax(TestBatch *batch) {
 }
 
 void
-TestQPSyntax_run_tests(TestQueryParserSyntax *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_query_parser_syntax(batch);
+TestQPSyntax_run(TestQueryParserSyntax *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 68);
+    test_query_parser_syntax(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserSyntax.cfh b/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
index 080fd4a..893dc06 100644
--- a/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
+++ b/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
@@ -23,13 +23,10 @@ class Lucy::Test::Search::TestQueryParserSyntax cnick TestQPSyntax
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestQueryParserSyntax*
-    new(TestFormatter *formatter);
-
-    inert TestQueryParserSyntax*
-    init(TestQueryParserSyntax *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestQueryParserSyntax *self);
+    Run(TestQueryParserSyntax *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestRangeQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestRangeQuery.c b/core/Lucy/Test/Search/TestRangeQuery.c
index fa1c698..94c6dfd 100644
--- a/core/Lucy/Test/Search/TestRangeQuery.c
+++ b/core/Lucy/Test/Search/TestRangeQuery.c
@@ -19,25 +19,19 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestRangeQuery.h"
 #include "Lucy/Search/RangeQuery.h"
 
 TestRangeQuery*
-TestRangeQuery_new(TestFormatter *formatter) {
-    TestRangeQuery *self = (TestRangeQuery*)VTable_Make_Obj(TESTRANGEQUERY);
-    return TestRangeQuery_init(self, formatter);
-}
-
-TestRangeQuery*
-TestRangeQuery_init(TestRangeQuery *self, TestFormatter *formatter) {
-    return (TestRangeQuery*)TestBatch_init((TestBatch*)self, 5, formatter);
+TestRangeQuery_new() {
+    return (TestRangeQuery*)VTable_Make_Obj(TESTRANGEQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     RangeQuery *query 
         = TestUtils_make_range_query("content", "foo", "phooey", true, true);
     RangeQuery *lo_term_differs 
@@ -51,15 +45,15 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     Obj        *dump  = (Obj*)RangeQuery_Dump(query);
     RangeQuery *clone = (RangeQuery*)RangeQuery_Load(lo_term_differs, dump);
 
-    TEST_FALSE(batch, RangeQuery_Equals(query, (Obj*)lo_term_differs),
+    TEST_FALSE(runner, RangeQuery_Equals(query, (Obj*)lo_term_differs),
                "Equals() false with different lower term");
-    TEST_FALSE(batch, RangeQuery_Equals(query, (Obj*)hi_term_differs),
+    TEST_FALSE(runner, RangeQuery_Equals(query, (Obj*)hi_term_differs),
                "Equals() false with different upper term");
-    TEST_FALSE(batch, RangeQuery_Equals(query, (Obj*)include_lower_differs),
+    TEST_FALSE(runner, RangeQuery_Equals(query, (Obj*)include_lower_differs),
                "Equals() false with different include_lower");
-    TEST_FALSE(batch, RangeQuery_Equals(query, (Obj*)include_upper_differs),
+    TEST_FALSE(runner, RangeQuery_Equals(query, (Obj*)include_upper_differs),
                "Equals() false with different include_upper");
-    TEST_TRUE(batch, RangeQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, RangeQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
 
     DECREF(query);
@@ -73,9 +67,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 
 
 void
-TestRangeQuery_run_tests(TestRangeQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestRangeQuery_run(TestRangeQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 5);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestRangeQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestRangeQuery.cfh b/core/Lucy/Test/Search/TestRangeQuery.cfh
index 241395d..78c188c 100644
--- a/core/Lucy/Test/Search/TestRangeQuery.cfh
+++ b/core/Lucy/Test/Search/TestRangeQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestRangeQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRangeQuery*
-    new(TestFormatter *formatter);
-
-    inert TestRangeQuery*
-    init(TestRangeQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestRangeQuery *self);
+    Run(TestRangeQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestReqOptQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestReqOptQuery.c b/core/Lucy/Test/Search/TestReqOptQuery.c
index a974c4a..79a2f15 100644
--- a/core/Lucy/Test/Search/TestReqOptQuery.c
+++ b/core/Lucy/Test/Search/TestReqOptQuery.c
@@ -19,7 +19,7 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Search/TestReqOptQuery.h"
@@ -27,18 +27,12 @@
 #include "Lucy/Search/LeafQuery.h"
 
 TestReqOptQuery*
-TestReqOptQuery_new(TestFormatter *formatter) {
-    TestReqOptQuery *self = (TestReqOptQuery*)VTable_Make_Obj(TESTREQOPTQUERY);
-    return TestReqOptQuery_init(self, formatter);
-}
-
-TestReqOptQuery*
-TestReqOptQuery_init(TestReqOptQuery *self, TestFormatter *formatter) {
-    return (TestReqOptQuery*)TestBatch_init((TestBatch*)self, 4, formatter);
+TestReqOptQuery_new() {
+    return (TestReqOptQuery*)VTable_Make_Obj(TESTREQOPTQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     Query *a_leaf  = (Query*)TestUtils_make_leaf_query(NULL, "a");
     Query *b_leaf  = (Query*)TestUtils_make_leaf_query(NULL, "b");
     Query *c_leaf  = (Query*)TestUtils_make_leaf_query(NULL, "c");
@@ -49,14 +43,14 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     RequiredOptionalQuery *clone
         = (RequiredOptionalQuery*)Obj_Load(dump, dump);
 
-    TEST_FALSE(batch, ReqOptQuery_Equals(query, (Obj*)kids_differ),
+    TEST_FALSE(runner, ReqOptQuery_Equals(query, (Obj*)kids_differ),
                "Different kids spoil Equals");
-    TEST_TRUE(batch, ReqOptQuery_Equals(query, (Obj*)boost_differs),
+    TEST_TRUE(runner, ReqOptQuery_Equals(query, (Obj*)boost_differs),
               "Equals with identical boosts");
     ReqOptQuery_Set_Boost(boost_differs, 1.5);
-    TEST_FALSE(batch, ReqOptQuery_Equals(query, (Obj*)boost_differs),
+    TEST_FALSE(runner, ReqOptQuery_Equals(query, (Obj*)boost_differs),
                "Different boost spoils Equals");
-    TEST_TRUE(batch, ReqOptQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, ReqOptQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
 
     DECREF(a_leaf);
@@ -70,9 +64,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestReqOptQuery_run_tests(TestReqOptQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestReqOptQuery_run(TestReqOptQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestReqOptQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestReqOptQuery.cfh b/core/Lucy/Test/Search/TestReqOptQuery.cfh
index 4e50151..2df8099 100644
--- a/core/Lucy/Test/Search/TestReqOptQuery.cfh
+++ b/core/Lucy/Test/Search/TestReqOptQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestReqOptQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestReqOptQuery*
-    new(TestFormatter *formatter);
-
-    inert TestReqOptQuery*
-    init(TestReqOptQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestReqOptQuery *self);
+    Run(TestReqOptQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestSeriesMatcher.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSeriesMatcher.c b/core/Lucy/Test/Search/TestSeriesMatcher.c
index 24ff6aa..64099d5 100644
--- a/core/Lucy/Test/Search/TestSeriesMatcher.c
+++ b/core/Lucy/Test/Search/TestSeriesMatcher.c
@@ -19,21 +19,15 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestSeriesMatcher.h"
 #include "Lucy/Search/BitVecMatcher.h"
 #include "Lucy/Search/SeriesMatcher.h"
 
 TestSeriesMatcher*
-TestSeriesMatcher_new(TestFormatter *formatter) {
-    TestSeriesMatcher *self = (TestSeriesMatcher*)VTable_Make_Obj(TESTSERIESMATCHER);
-    return TestSeriesMatcher_init(self, formatter);
-}
-
-TestSeriesMatcher*
-TestSeriesMatcher_init(TestSeriesMatcher *self, TestFormatter *formatter) {
-    return (TestSeriesMatcher*)TestBatch_init((TestBatch*)self, 135, formatter);
+TestSeriesMatcher_new() {
+    return (TestSeriesMatcher*)VTable_Make_Obj(TESTSERIESMATCHER);
 }
 
 static SeriesMatcher*
@@ -82,7 +76,7 @@ S_generate_match_list(int32_t first, int32_t max, int32_t doc_inc) {
 }
 
 static void
-S_do_test_matrix(TestBatch *batch, int32_t doc_max, int32_t first_doc_id,
+S_do_test_matrix(TestBatchRunner *runner, int32_t doc_max, int32_t first_doc_id,
                  int32_t doc_inc, int32_t offset_inc) {
     I32Array *doc_ids
         = S_generate_match_list(first_doc_id, doc_max, doc_inc);
@@ -97,7 +91,7 @@ S_do_test_matrix(TestBatch *batch, int32_t doc_max, int32_t first_doc_id,
         if (got != I32Arr_Get(doc_ids, num_in_agreement)) { break; }
         num_in_agreement++;
     }
-    TEST_INT_EQ(batch, num_in_agreement, I32Arr_Get_Size(doc_ids),
+    TEST_INT_EQ(runner, num_in_agreement, I32Arr_Get_Size(doc_ids),
                 "doc_max=%d first_doc_id=%d doc_inc=%d offset_inc=%d",
                 doc_max, first_doc_id, doc_inc, offset_inc);
 
@@ -107,7 +101,7 @@ S_do_test_matrix(TestBatch *batch, int32_t doc_max, int32_t first_doc_id,
 }
 
 static void
-test_matrix(TestBatch *batch) {
+test_matrix(TestBatchRunner *runner) {
     int32_t doc_max_nums[]     = { 10, 100, 1000, 0 };
     int32_t first_doc_ids[]    = { 1, 2, 10, 0 };
     int32_t doc_inc_nums[]     = { 20, 13, 9, 4, 2, 0 };
@@ -126,7 +120,7 @@ test_matrix(TestBatch *batch) {
                         continue;
                     }
                     else {
-                        S_do_test_matrix(batch, doc_max, first_doc_id,
+                        S_do_test_matrix(runner, doc_max, first_doc_id,
                                          doc_inc, offset_inc);
                     }
                 }
@@ -136,9 +130,9 @@ test_matrix(TestBatch *batch) {
 }
 
 void
-TestSeriesMatcher_run_tests(TestSeriesMatcher *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_matrix(batch);
+TestSeriesMatcher_run(TestSeriesMatcher *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 135);
+    test_matrix(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestSeriesMatcher.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSeriesMatcher.cfh b/core/Lucy/Test/Search/TestSeriesMatcher.cfh
index 476156f..fa89085 100644
--- a/core/Lucy/Test/Search/TestSeriesMatcher.cfh
+++ b/core/Lucy/Test/Search/TestSeriesMatcher.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestSeriesMatcher
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSeriesMatcher*
-    new(TestFormatter *formatter);
-
-    inert TestSeriesMatcher*
-    init(TestSeriesMatcher *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSeriesMatcher *self);
+    Run(TestSeriesMatcher *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestSortSpec.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSortSpec.c b/core/Lucy/Test/Search/TestSortSpec.c
index 9b4dd3b..841e9ba 100644
--- a/core/Lucy/Test/Search/TestSortSpec.c
+++ b/core/Lucy/Test/Search/TestSortSpec.c
@@ -21,7 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestSortSpec.h"
@@ -71,14 +71,8 @@ static CharBuf *random_int32s_cb;
 static CharBuf *random_int64s_cb;
 
 TestSortSpec*
-TestSortSpec_new(TestFormatter *formatter) {
-    TestSortSpec *self = (TestSortSpec*)VTable_Make_Obj(TESTSORTSPEC);
-    return TestSortSpec_init(self, formatter);
-}
-
-TestSortSpec*
-TestSortSpec_init(TestSortSpec *self, TestFormatter *formatter) {
-    return (TestSortSpec*)TestBatch_init((TestBatch*)self, 18, formatter);
+TestSortSpec_new() {
+    return (TestSortSpec*)VTable_Make_Obj(TESTSORTSPEC);
 }
 
 static void
@@ -387,7 +381,7 @@ S_attempt_sorted_search(void *context) {
 }
 
 static void
-test_sort_spec(TestBatch *batch) {
+test_sort_spec(TestBatchRunner *runner) {
     RAMFolder *folder  = RAMFolder_new(NULL);
     Schema    *schema  = S_create_schema();
     Indexer   *indexer = NULL;
@@ -457,12 +451,12 @@ test_sort_spec(TestBatch *batch) {
     VA_Push(wanted, INCREF(airplane_cb));
     VA_Push(wanted, INCREF(bike_cb));
     VA_Push(wanted, INCREF(car_cb));
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)wanted), "sort by one criteria");
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)wanted), "sort by one criteria");
     DECREF(results);
 
 #ifdef LUCY_VALGRIND
-    SKIP(batch, "known leaks");
-    SKIP(batch, "known leaks");
+    SKIP(runner, "known leaks");
+    SKIP(runner, "known leaks");
 #else
     Err *error;
     SortContext sort_ctx;
@@ -470,7 +464,7 @@ test_sort_spec(TestBatch *batch) {
 
     sort_ctx.sort_field = nope_cb;
     error = Err_trap(S_attempt_sorted_search, &sort_ctx);
-    TEST_TRUE(batch, error != NULL
+    TEST_TRUE(runner, error != NULL
               && Err_Is_A(error, ERR)
               && CB_Find_Str(Err_Get_Mess(error), "sortable", 8) != -1,
               "sorting on a non-sortable field throws an error");
@@ -478,7 +472,7 @@ test_sort_spec(TestBatch *batch) {
 
     sort_ctx.sort_field = unknown_cb;
     error = Err_trap(S_attempt_sorted_search, &sort_ctx);
-    TEST_TRUE(batch, error != NULL
+    TEST_TRUE(runner, error != NULL
               && Err_Is_A(error, ERR)
               && CB_Find_Str(Err_Get_Mess(error), "sortable", 8) != -1,
               "sorting on an unknown field throws an error");
@@ -491,7 +485,7 @@ test_sort_spec(TestBatch *batch) {
     VA_Push(wanted, INCREF(bike_cb));
     VA_Push(wanted, INCREF(car_cb));
     VA_Push(wanted, INCREF(airplane_cb));
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)wanted), "sort by one criteria");
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)wanted), "sort by one criteria");
     DECREF(results);
 
     results = S_test_sorted_search(searcher, vehicle_cb, 100,
@@ -500,7 +494,7 @@ test_sort_spec(TestBatch *batch) {
     VA_Push(wanted, INCREF(car_cb));
     VA_Push(wanted, INCREF(bike_cb));
     VA_Push(wanted, INCREF(airplane_cb));
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)wanted), "reverse sort");
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)wanted), "reverse sort");
     DECREF(results);
 
     results = S_test_sorted_search(searcher, vehicle_cb, 100,
@@ -509,7 +503,7 @@ test_sort_spec(TestBatch *batch) {
     VA_Push(wanted, INCREF(airplane_cb));
     VA_Push(wanted, INCREF(bike_cb));
     VA_Push(wanted, INCREF(car_cb));
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)wanted), "multiple criteria");
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)wanted), "multiple criteria");
     DECREF(results);
 
     results = S_test_sorted_search(searcher, vehicle_cb, 100,
@@ -518,7 +512,7 @@ test_sort_spec(TestBatch *batch) {
     VA_Push(wanted, INCREF(airplane_cb));
     VA_Push(wanted, INCREF(car_cb));
     VA_Push(wanted, INCREF(bike_cb));
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)wanted),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)wanted),
               "multiple criteria with reverse");
     DECREF(results);
 
@@ -526,38 +520,38 @@ test_sort_spec(TestBatch *batch) {
                                    speed_cb, true, NULL);
     results2 = S_test_sorted_search(searcher, vehicle_cb, 100,
                                     sloth_cb, false, NULL);
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)results2),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)results2),
               "FieldType_Compare_Values");
     DECREF(results2);
     DECREF(results);
 
     results = S_test_sorted_search(searcher, random_cb, 100,
                                    name_cb, false, NULL);
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)random_strings),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)random_strings),
               "random strings");
     DECREF(results);
 
     results = S_test_sorted_search(searcher, random_int32s_cb, 100,
                                    int32_cb, false, NULL);
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)random_int32s),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)random_int32s),
               "int32");
     DECREF(results);
 
     results = S_test_sorted_search(searcher, random_int64s_cb, 100,
                                    int64_cb, false, NULL);
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)random_int64s),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)random_int64s),
               "int64");
     DECREF(results);
 
     results = S_test_sorted_search(searcher, random_float32s_cb, 100,
                                    float32_cb, false, NULL);
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)random_float32s),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)random_float32s),
               "float32");
     DECREF(results);
 
     results = S_test_sorted_search(searcher, random_float64s_cb, 100,
                                    float64_cb, false, NULL);
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)random_float64s),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)random_float64s),
               "float64");
     DECREF(results);
 
@@ -568,7 +562,7 @@ test_sort_spec(TestBatch *batch) {
     VA_Push(wanted, INCREF(airplane_cb));
     VA_Push(wanted, INCREF(bike_cb));
     VA_Push(wanted, INCREF(car_cb));
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)wanted),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)wanted),
               "sorting on field with no values sorts by doc id");
     DECREF(results);
     DECREF(bbbcca_cb);
@@ -580,7 +574,7 @@ test_sort_spec(TestBatch *batch) {
     VA_Clear(wanted);
     VA_Push(wanted, INCREF(car_cb));
     VA_Push(wanted, INCREF(nn_cb));
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)wanted),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)wanted),
               "doc with NULL value sorts last");
     DECREF(results);
     DECREF(nn_cb);
@@ -591,7 +585,7 @@ test_sort_spec(TestBatch *batch) {
     results2 = S_test_sorted_search(searcher, num_cb, 30,
                                     name_cb, false, NULL);
     VA_Resize(results2, 10);
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)results2),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)results2),
               "same order regardless of queue size");
     DECREF(results2);
     DECREF(results);
@@ -601,7 +595,7 @@ test_sort_spec(TestBatch *batch) {
     results2 = S_test_sorted_search(searcher, num_cb, 30,
                                     name_cb, true, NULL);
     VA_Resize(results2, 10);
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)results2),
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)results2),
               "same order regardless of queue size (reverse sort)");
     DECREF(results2);
     DECREF(results);
@@ -621,7 +615,7 @@ test_sort_spec(TestBatch *batch) {
     VA_Push(wanted, INCREF(airplane_cb));
     VA_Push(wanted, INCREF(bike_cb));
     VA_Push(wanted, INCREF(car_cb));
-    TEST_TRUE(batch, VA_Equals(results, (Obj*)wanted), "Multi-segment sort");
+    TEST_TRUE(runner, VA_Equals(results, (Obj*)wanted), "Multi-segment sort");
     DECREF(results);
     DECREF(searcher);
 
@@ -637,10 +631,10 @@ test_sort_spec(TestBatch *batch) {
 }
 
 void
-TestSortSpec_run_tests(TestSortSpec *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestSortSpec_run(TestSortSpec *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 18);
     S_init_strings();
-    test_sort_spec(batch);
+    test_sort_spec(runner);
     S_destroy_strings();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestSortSpec.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSortSpec.cfh b/core/Lucy/Test/Search/TestSortSpec.cfh
index e5be81e..8b94bae 100644
--- a/core/Lucy/Test/Search/TestSortSpec.cfh
+++ b/core/Lucy/Test/Search/TestSortSpec.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestSortSpec
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSortSpec*
-    new(TestFormatter *formatter);
-
-    inert TestSortSpec*
-    init(TestSortSpec *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSortSpec *self);
+    Run(TestSortSpec *self, TestBatchRunner *runner);
 }
 
 class Lucy::Test::Search::TestReverseType inherits Lucy::Plan::Int32Type {

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestSpan.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSpan.c b/core/Lucy/Test/Search/TestSpan.c
index c2f9d60..f97a130 100644
--- a/core/Lucy/Test/Search/TestSpan.c
+++ b/core/Lucy/Test/Search/TestSpan.c
@@ -18,42 +18,36 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestSpan.h"
 #include "Lucy/Search/Span.h"
 
 TestSpan*
-TestSpan_new(TestFormatter *formatter) {
-    TestSpan *self = (TestSpan*)VTable_Make_Obj(TESTSPAN);
-    return TestSpan_init(self, formatter);
-}
-
-TestSpan*
-TestSpan_init(TestSpan *self, TestFormatter *formatter) {
-    return (TestSpan*)TestBatch_init((TestBatch*)self, 6, formatter);
+TestSpan_new() {
+    return (TestSpan*)VTable_Make_Obj(TESTSPAN);
 }
 
 void 
-test_span_init_values(TestBatch *batch) {
+test_span_init_values(TestBatchRunner *runner) {
     Span* span = Span_new(2,3,7);
-    TEST_INT_EQ(batch, Span_Get_Offset(span), 2, "get_offset" );
-    TEST_INT_EQ(batch, Span_Get_Length(span), 3, "get_length" );
-    TEST_INT_EQ(batch, Span_Get_Weight(span), 7, "get_weight" );
+    TEST_INT_EQ(runner, Span_Get_Offset(span), 2, "get_offset" );
+    TEST_INT_EQ(runner, Span_Get_Length(span), 3, "get_length" );
+    TEST_INT_EQ(runner, Span_Get_Weight(span), 7, "get_weight" );
 
     Span_Set_Offset(span, 10);
     Span_Set_Length(span, 1);
     Span_Set_Weight(span, 4);
 
-    TEST_INT_EQ(batch, Span_Get_Offset(span), 10, "set_offset" );
-    TEST_INT_EQ(batch, Span_Get_Length(span), 1, "set_length" );
-    TEST_INT_EQ(batch, Span_Get_Weight(span), 4, "set_weight" );
+    TEST_INT_EQ(runner, Span_Get_Offset(span), 10, "set_offset" );
+    TEST_INT_EQ(runner, Span_Get_Length(span), 1, "set_length" );
+    TEST_INT_EQ(runner, Span_Get_Weight(span), 4, "set_weight" );
 
     DECREF(span);
 }
 
 void
-TestSpan_run_tests(TestSpan *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_span_init_values(batch);
+TestSpan_run(TestSpan *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
+    test_span_init_values(runner);
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestSpan.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSpan.cfh b/core/Lucy/Test/Search/TestSpan.cfh
index bc64c8e..d84c45f 100644
--- a/core/Lucy/Test/Search/TestSpan.cfh
+++ b/core/Lucy/Test/Search/TestSpan.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestSpan
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSpan*
-    new(TestFormatter *formatter);
-
-    inert TestSpan*
-    init(TestSpan *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSpan *self);
+    Run(TestSpan *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestTermQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestTermQuery.c b/core/Lucy/Test/Search/TestTermQuery.c
index 46ddf04..b732a1b 100644
--- a/core/Lucy/Test/Search/TestTermQuery.c
+++ b/core/Lucy/Test/Search/TestTermQuery.c
@@ -19,25 +19,19 @@
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Search/TestTermQuery.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Search/TermQuery.h"
 
 TestTermQuery*
-TestTermQuery_new(TestFormatter *formatter) {
-    TestTermQuery *self = (TestTermQuery*)VTable_Make_Obj(TESTTERMQUERY);
-    return TestTermQuery_init(self, formatter);
-}
-
-TestTermQuery*
-TestTermQuery_init(TestTermQuery *self, TestFormatter *formatter) {
-    return (TestTermQuery*)TestBatch_init((TestBatch*)self, 4, formatter);
+TestTermQuery_new() {
+    return (TestTermQuery*)VTable_Make_Obj(TESTTERMQUERY);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     TermQuery *query         = TestUtils_make_term_query("content", "foo");
     TermQuery *field_differs = TestUtils_make_term_query("stuff", "foo");
     TermQuery *term_differs  = TestUtils_make_term_query("content", "bar");
@@ -45,14 +39,14 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     Obj       *dump          = (Obj*)TermQuery_Dump(query);
     TermQuery *clone         = (TermQuery*)TermQuery_Load(term_differs, dump);
 
-    TEST_FALSE(batch, TermQuery_Equals(query, (Obj*)field_differs),
+    TEST_FALSE(runner, TermQuery_Equals(query, (Obj*)field_differs),
                "Equals() false with different field");
-    TEST_FALSE(batch, TermQuery_Equals(query, (Obj*)term_differs),
+    TEST_FALSE(runner, TermQuery_Equals(query, (Obj*)term_differs),
                "Equals() false with different term");
     TermQuery_Set_Boost(boost_differs, 0.5);
-    TEST_FALSE(batch, TermQuery_Equals(query, (Obj*)boost_differs),
+    TEST_FALSE(runner, TermQuery_Equals(query, (Obj*)boost_differs),
                "Equals() false with different boost");
-    TEST_TRUE(batch, TermQuery_Equals(query, (Obj*)clone),
+    TEST_TRUE(runner, TermQuery_Equals(query, (Obj*)clone),
               "Dump => Load round trip");
 
     DECREF(query);
@@ -64,9 +58,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestTermQuery_run_tests(TestTermQuery *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestTermQuery_run(TestTermQuery *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Search/TestTermQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestTermQuery.cfh b/core/Lucy/Test/Search/TestTermQuery.cfh
index 3cdcac2..ac997aa 100644
--- a/core/Lucy/Test/Search/TestTermQuery.cfh
+++ b/core/Lucy/Test/Search/TestTermQuery.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Search::TestTermQuery
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestTermQuery*
-    new(TestFormatter *formatter);
-
-    inert TestTermQuery*
-    init(TestTermQuery *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestTermQuery *self);
+    Run(TestTermQuery *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestCompoundFileReader.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileReader.c b/core/Lucy/Test/Store/TestCompoundFileReader.c
index 425611c..453e454 100644
--- a/core/Lucy/Test/Store/TestCompoundFileReader.c
+++ b/core/Lucy/Test/Store/TestCompoundFileReader.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestCompoundFileReader.h"
 #include "Lucy/Store/CompoundFileReader.h"
@@ -39,14 +39,8 @@ static CharBuf *seg_1       = NULL;
 static CharBuf *stuff       = NULL;
 
 TestCompoundFileReader*
-TestCFReader_new(TestFormatter *formatter) {
-    TestCompoundFileReader *self = (TestCompoundFileReader*)VTable_Make_Obj(TESTCOMPOUNDFILEREADER);
-    return TestCFReader_init(self, formatter);
-}
-
-TestCompoundFileReader*
-TestCFReader_init(TestCompoundFileReader *self, TestFormatter *formatter) {
-    return (TestCompoundFileReader*)TestBatch_init((TestBatch*)self, 48, formatter);
+TestCFReader_new() {
+    return (TestCompoundFileReader*)VTable_Make_Obj(TESTCOMPOUNDFILEREADER);
 }
 
 static void
@@ -90,7 +84,7 @@ S_folder_with_contents() {
 }
 
 static void
-test_open(TestBatch *batch) {
+test_open(TestBatchRunner *runner) {
     Folder *real_folder;
     CompoundFileReader *cf_reader;
     Hash *metadata;
@@ -99,9 +93,9 @@ test_open(TestBatch *batch) {
     real_folder = S_folder_with_contents();
     Folder_Delete(real_folder, cfmeta_file);
     cf_reader = CFReader_open(real_folder);
-    TEST_TRUE(batch, cf_reader == NULL,
+    TEST_TRUE(runner, cf_reader == NULL,
               "Return NULL when cfmeta file missing");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Set Err_error when cfmeta file missing");
     DECREF(real_folder);
 
@@ -109,9 +103,9 @@ test_open(TestBatch *batch) {
     real_folder = S_folder_with_contents();
     Folder_Delete(real_folder, cf_file);
     cf_reader = CFReader_open(real_folder);
-    TEST_TRUE(batch, cf_reader == NULL,
+    TEST_TRUE(runner, cf_reader == NULL,
               "Return NULL when cf.dat file missing");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Set Err_error when cf.dat file missing");
     DECREF(real_folder);
 
@@ -122,9 +116,9 @@ test_open(TestBatch *batch) {
     Folder_Delete(real_folder, cfmeta_file);
     Json_spew_json((Obj*)metadata, real_folder, cfmeta_file);
     cf_reader = CFReader_open(real_folder);
-    TEST_TRUE(batch, cf_reader == NULL,
+    TEST_TRUE(runner, cf_reader == NULL,
               "Return NULL when format is invalid");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Set Err_error when format is invalid");
 
     Err_set_error(NULL);
@@ -132,9 +126,9 @@ test_open(TestBatch *batch) {
     Folder_Delete(real_folder, cfmeta_file);
     Json_spew_json((Obj*)metadata, real_folder, cfmeta_file);
     cf_reader = CFReader_open(real_folder);
-    TEST_TRUE(batch, cf_reader == NULL,
+    TEST_TRUE(runner, cf_reader == NULL,
               "Return NULL when format is too recent");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Set Err_error when format too recent");
 
     Err_set_error(NULL);
@@ -142,9 +136,9 @@ test_open(TestBatch *batch) {
     Folder_Delete(real_folder, cfmeta_file);
     Json_spew_json((Obj*)metadata, real_folder, cfmeta_file);
     cf_reader = CFReader_open(real_folder);
-    TEST_TRUE(batch, cf_reader == NULL,
+    TEST_TRUE(runner, cf_reader == NULL,
               "Return NULL when format key is missing");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Set Err_error when format key is missing");
 
     Hash_Store_Str(metadata, "format", 6,
@@ -153,9 +147,9 @@ test_open(TestBatch *batch) {
     Folder_Delete(real_folder, cfmeta_file);
     Json_spew_json((Obj*)metadata, real_folder, cfmeta_file);
     cf_reader = CFReader_open(real_folder);
-    TEST_TRUE(batch, cf_reader == NULL,
+    TEST_TRUE(runner, cf_reader == NULL,
               "Return NULL when files key is missing");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Set Err_error when files key is missing");
 
     DECREF(metadata);
@@ -163,43 +157,43 @@ test_open(TestBatch *batch) {
 }
 
 static void
-test_Local_MkDir_and_Find_Folder(TestBatch *batch) {
+test_Local_MkDir_and_Find_Folder(TestBatchRunner *runner) {
     Folder *real_folder = S_folder_with_contents();
     CompoundFileReader *cf_reader = CFReader_open(real_folder);
 
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                CFReader_Local_Is_Directory(cf_reader, stuff),
                "Local_Is_Directory returns false for non-existent entry");
 
-    TEST_TRUE(batch, CFReader_MkDir(cf_reader, stuff),
+    TEST_TRUE(runner, CFReader_MkDir(cf_reader, stuff),
               "MkDir returns true");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               Folder_Find_Folder(real_folder, stuff) != NULL,
               "Local_MkDir pass-through");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               Folder_Find_Folder(real_folder, stuff)
               == CFReader_Find_Folder(cf_reader, stuff),
               "Local_Find_Folder pass-through");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CFReader_Local_Is_Directory(cf_reader, stuff),
               "Local_Is_Directory pass through");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, CFReader_MkDir(cf_reader, stuff),
+    TEST_FALSE(runner, CFReader_MkDir(cf_reader, stuff),
                "MkDir returns false when dir already exists");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "MkDir sets Err_error when dir already exists");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, CFReader_MkDir(cf_reader, foo),
+    TEST_FALSE(runner, CFReader_MkDir(cf_reader, foo),
                "MkDir returns false when virtual file exists");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "MkDir sets Err_error when virtual file exists");
 
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CFReader_Find_Folder(cf_reader, foo) == NULL,
               "Virtual file not reported as directory");
-    TEST_FALSE(batch, CFReader_Local_Is_Directory(cf_reader, foo),
+    TEST_FALSE(runner, CFReader_Local_Is_Directory(cf_reader, foo),
                "Local_Is_Directory returns false for virtual file");
 
     DECREF(real_folder);
@@ -207,36 +201,36 @@ test_Local_MkDir_and_Find_Folder(TestBatch *batch) {
 }
 
 static void
-test_Local_Delete_and_Exists(TestBatch *batch) {
+test_Local_Delete_and_Exists(TestBatchRunner *runner) {
     Folder *real_folder = S_folder_with_contents();
     CompoundFileReader *cf_reader = CFReader_open(real_folder);
 
     CFReader_MkDir(cf_reader, stuff);
-    TEST_TRUE(batch, CFReader_Local_Exists(cf_reader, stuff),
+    TEST_TRUE(runner, CFReader_Local_Exists(cf_reader, stuff),
               "pass through for Local_Exists");
-    TEST_TRUE(batch, CFReader_Local_Exists(cf_reader, foo),
+    TEST_TRUE(runner, CFReader_Local_Exists(cf_reader, foo),
               "Local_Exists returns true for virtual file");
 
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CFReader_Local_Exists(cf_reader, cfmeta_file),
               "cfmeta file exists");
 
-    TEST_TRUE(batch, CFReader_Local_Delete(cf_reader, stuff),
+    TEST_TRUE(runner, CFReader_Local_Delete(cf_reader, stuff),
               "Local_Delete returns true when zapping real entity");
-    TEST_FALSE(batch, CFReader_Local_Exists(cf_reader, stuff),
+    TEST_FALSE(runner, CFReader_Local_Exists(cf_reader, stuff),
                "Local_Exists returns false after real entity zapped");
 
-    TEST_TRUE(batch, CFReader_Local_Delete(cf_reader, foo),
+    TEST_TRUE(runner, CFReader_Local_Delete(cf_reader, foo),
               "Local_Delete returns true when zapping virtual file");
-    TEST_FALSE(batch, CFReader_Local_Exists(cf_reader, foo),
+    TEST_FALSE(runner, CFReader_Local_Exists(cf_reader, foo),
                "Local_Exists returns false after virtual file zapped");
 
-    TEST_TRUE(batch, CFReader_Local_Delete(cf_reader, bar),
+    TEST_TRUE(runner, CFReader_Local_Delete(cf_reader, bar),
               "Local_Delete returns true when zapping last virtual file");
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                CFReader_Local_Exists(cf_reader, cfmeta_file),
                "cfmeta file deleted when last virtual file deleted");
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                CFReader_Local_Exists(cf_reader, cf_file),
                "compound data file deleted when last virtual file deleted");
 
@@ -245,7 +239,7 @@ test_Local_Delete_and_Exists(TestBatch *batch) {
 }
 
 static void
-test_Local_Open_Dir(TestBatch *batch) {
+test_Local_Open_Dir(TestBatchRunner *runner) {
 
     Folder *real_folder = S_folder_with_contents();
     CompoundFileReader *cf_reader = CFReader_open(real_folder);
@@ -269,9 +263,9 @@ test_Local_Open_Dir(TestBatch *batch) {
         }
     }
 
-    TEST_TRUE(batch, saw_foo, "DirHandle iterated over virtual file");
-    TEST_TRUE(batch, saw_stuff, "DirHandle iterated over real directory");
-    TEST_TRUE(batch, stuff_was_dir,
+    TEST_TRUE(runner, saw_foo, "DirHandle iterated over virtual file");
+    TEST_TRUE(runner, saw_stuff, "DirHandle iterated over real directory");
+    TEST_TRUE(runner, stuff_was_dir,
               "DirHandle knew that real entry was dir");
 
     DECREF(dh);
@@ -280,7 +274,7 @@ test_Local_Open_Dir(TestBatch *batch) {
 }
 
 static void
-test_Local_Open_FileHandle(TestBatch *batch) {
+test_Local_Open_FileHandle(TestBatchRunner *runner) {
     Folder *real_folder = S_folder_with_contents();
     CompoundFileReader *cf_reader = CFReader_open(real_folder);
     FileHandle *fh;
@@ -292,24 +286,24 @@ test_Local_Open_FileHandle(TestBatch *batch) {
 
     fh = CFReader_Local_Open_FileHandle(cf_reader, baz,
                                         FH_READ_ONLY);
-    TEST_TRUE(batch, fh != NULL,
+    TEST_TRUE(runner, fh != NULL,
               "Local_Open_FileHandle pass-through for real file");
     DECREF(fh);
 
     Err_set_error(NULL);
     fh = CFReader_Local_Open_FileHandle(cf_reader, stuff,
                                         FH_READ_ONLY);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "Local_Open_FileHandle for non-existent file returns NULL");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Local_Open_FileHandle for non-existent file sets Err_error");
 
     Err_set_error(NULL);
     fh = CFReader_Local_Open_FileHandle(cf_reader, foo,
                                         FH_READ_ONLY);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "Local_Open_FileHandle for virtual file returns NULL");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Local_Open_FileHandle for virtual file sets Err_error");
 
     DECREF(cf_reader);
@@ -317,15 +311,15 @@ test_Local_Open_FileHandle(TestBatch *batch) {
 }
 
 static void
-test_Local_Open_In(TestBatch *batch) {
+test_Local_Open_In(TestBatchRunner *runner) {
     Folder *real_folder = S_folder_with_contents();
     CompoundFileReader *cf_reader = CFReader_open(real_folder);
     InStream *instream;
 
     instream = CFReader_Local_Open_In(cf_reader, foo);
-    TEST_TRUE(batch, instream != NULL,
+    TEST_TRUE(runner, instream != NULL,
               "Local_Open_In for virtual file");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Starts_With(InStream_Get_Filename(instream), CFReader_Get_Path(cf_reader)),
               "InStream's path includes directory");
     DECREF(instream);
@@ -335,15 +329,15 @@ test_Local_Open_In(TestBatch *batch) {
     OutStream_Close(outstream);
     DECREF(outstream);
     instream = CFReader_Local_Open_In(cf_reader, baz);
-    TEST_TRUE(batch, instream != NULL,
+    TEST_TRUE(runner, instream != NULL,
               "Local_Open_In pass-through for real file");
     DECREF(instream);
 
     Err_set_error(NULL);
     instream = CFReader_Local_Open_In(cf_reader, stuff);
-    TEST_TRUE(batch, instream == NULL,
+    TEST_TRUE(runner, instream == NULL,
               "Local_Open_In for non-existent file returns NULL");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Local_Open_In for non-existent file sets Err_error");
 
     DECREF(cf_reader);
@@ -351,31 +345,31 @@ test_Local_Open_In(TestBatch *batch) {
 }
 
 static void
-test_Close(TestBatch *batch) {
+test_Close(TestBatchRunner *runner) {
     Folder *real_folder = S_folder_with_contents();
     CompoundFileReader *cf_reader = CFReader_open(real_folder);
 
     CFReader_Close(cf_reader);
-    PASS(batch, "Close completes without incident");
+    PASS(runner, "Close completes without incident");
 
     CFReader_Close(cf_reader);
-    PASS(batch, "Calling Close() multiple times is ok");
+    PASS(runner, "Calling Close() multiple times is ok");
 
     DECREF(cf_reader);
     DECREF(real_folder);
 }
 
 void
-TestCFReader_run_tests(TestCompoundFileReader *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestCFReader_run(TestCompoundFileReader *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 48);
     S_init_strings();
-    test_open(batch);
-    test_Local_MkDir_and_Find_Folder(batch);
-    test_Local_Delete_and_Exists(batch);
-    test_Local_Open_Dir(batch);
-    test_Local_Open_FileHandle(batch);
-    test_Local_Open_In(batch);
-    test_Close(batch);
+    test_open(runner);
+    test_Local_MkDir_and_Find_Folder(runner);
+    test_Local_Delete_and_Exists(runner);
+    test_Local_Open_Dir(runner);
+    test_Local_Open_FileHandle(runner);
+    test_Local_Open_In(runner);
+    test_Close(runner);
     S_destroy_strings();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestCompoundFileReader.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileReader.cfh b/core/Lucy/Test/Store/TestCompoundFileReader.cfh
index bd2a23b..24f976b 100644
--- a/core/Lucy/Test/Store/TestCompoundFileReader.cfh
+++ b/core/Lucy/Test/Store/TestCompoundFileReader.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestCompoundFileReader cnick TestCFReader
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestCompoundFileReader*
-    new(TestFormatter *formatter);
-
-    inert TestCompoundFileReader*
-    init(TestCompoundFileReader *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestCompoundFileReader *self);
+    Run(TestCompoundFileReader *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestCompoundFileWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileWriter.c b/core/Lucy/Test/Store/TestCompoundFileWriter.c
index c315ba1..bbd9575 100644
--- a/core/Lucy/Test/Store/TestCompoundFileWriter.c
+++ b/core/Lucy/Test/Store/TestCompoundFileWriter.c
@@ -17,7 +17,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestCompoundFileWriter.h"
 #include "Lucy/Store/CompoundFileWriter.h"
@@ -34,14 +34,8 @@ static CharBuf *bar         = NULL;
 static CharBuf *seg_1       = NULL;
 
 TestCompoundFileWriter*
-TestCFWriter_new(TestFormatter *formatter) {
-    TestCompoundFileWriter *self = (TestCompoundFileWriter*)VTable_Make_Obj(TESTCOMPOUNDFILEWRITER);
-    return TestCFWriter_init(self, formatter);
-}
-
-TestCompoundFileWriter*
-TestCFWriter_init(TestCompoundFileWriter *self, TestFormatter *formatter) {
-    return (TestCompoundFileWriter*)TestBatch_init((TestBatch*)self, 7, formatter);
+TestCFWriter_new() {
+    return (TestCompoundFileWriter*)VTable_Make_Obj(TESTCOMPOUNDFILEWRITER);
 }
 
 static void
@@ -79,7 +73,7 @@ S_folder_with_contents() {
 }
 
 static void
-test_Consolidate(TestBatch *batch) {
+test_Consolidate(TestBatchRunner *runner) {
     Folder *folder = S_folder_with_contents();
     FileHandle *fh;
 
@@ -93,23 +87,23 @@ test_Consolidate(TestBatch *batch) {
 
     CompoundFileWriter *cf_writer = CFWriter_new(folder);
     CFWriter_Consolidate(cf_writer);
-    PASS(batch, "Consolidate completes despite leftover files");
+    PASS(runner, "Consolidate completes despite leftover files");
     DECREF(cf_writer);
 
-    TEST_TRUE(batch, Folder_Exists(folder, cf_file),
+    TEST_TRUE(runner, Folder_Exists(folder, cf_file),
               "cf.dat file written");
-    TEST_TRUE(batch, Folder_Exists(folder, cfmeta_file),
+    TEST_TRUE(runner, Folder_Exists(folder, cfmeta_file),
               "cfmeta.json file written");
-    TEST_FALSE(batch, Folder_Exists(folder, foo),
+    TEST_FALSE(runner, Folder_Exists(folder, foo),
                "original file zapped");
-    TEST_FALSE(batch, Folder_Exists(folder, cfmeta_temp),
+    TEST_FALSE(runner, Folder_Exists(folder, cfmeta_temp),
                "detritus from failed consolidation zapped");
 
     DECREF(folder);
 }
 
 static void
-test_offsets(TestBatch *batch) {
+test_offsets(TestBatchRunner *runner) {
     Folder *folder = S_folder_with_contents();
     CompoundFileWriter *cf_writer = CFWriter_new(folder);
     Hash    *cf_metadata;
@@ -126,7 +120,7 @@ test_offsets(TestBatch *batch) {
     Obj     *filestats;
     bool     offsets_ok = true;
 
-    TEST_TRUE(batch, Hash_Get_Size(files) > 0, "Multiple files");
+    TEST_TRUE(runner, Hash_Get_Size(files) > 0, "Multiple files");
 
     Hash_Iterate(files);
     while (Hash_Next(files, (Obj**)&file, &filestats)) {
@@ -135,13 +129,13 @@ test_offsets(TestBatch *batch) {
         int64_t offs = Obj_To_I64(offset);
         if (offs % 8 != 0) {
             offsets_ok = false;
-            FAIL(batch, "Offset %" PRId64 " for %s not a multiple of 8",
+            FAIL(runner, "Offset %" PRId64 " for %s not a multiple of 8",
                  offset, CB_Get_Ptr8(file));
             break;
         }
     }
     if (offsets_ok) {
-        PASS(batch, "All offsets are multiples of 8");
+        PASS(runner, "All offsets are multiples of 8");
     }
 
     DECREF(cf_metadata);
@@ -150,11 +144,11 @@ test_offsets(TestBatch *batch) {
 }
 
 void
-TestCFWriter_run_tests(TestCompoundFileWriter *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestCFWriter_run(TestCompoundFileWriter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 7);
     S_init_strings();
-    test_Consolidate(batch);
-    test_offsets(batch);
+    test_Consolidate(runner);
+    test_offsets(runner);
     S_destroy_strings();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileWriter.cfh b/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
index 407e6d7..7f01e8f 100644
--- a/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
+++ b/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestCompoundFileWriter cnick TestCFWriter
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestCompoundFileWriter*
-    new(TestFormatter *formatter);
-
-    inert TestCompoundFileWriter*
-    init(TestCompoundFileWriter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestCompoundFileWriter *self);
+    Run(TestCompoundFileWriter *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFSDirHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSDirHandle.c b/core/Lucy/Test/Store/TestFSDirHandle.c
index 59530ce..7026ef1 100644
--- a/core/Lucy/Test/Store/TestFSDirHandle.c
+++ b/core/Lucy/Test/Store/TestFSDirHandle.c
@@ -27,7 +27,7 @@
   #include <unistd.h>
 #endif
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFSDirHandle.h"
 #include "Lucy/Store/FSDirHandle.h"
@@ -35,18 +35,12 @@
 #include "Lucy/Store/OutStream.h"
 
 TestFSDirHandle*
-TestFSDH_new(TestFormatter *formatter) {
-    TestFSDirHandle *self = (TestFSDirHandle*)VTable_Make_Obj(TESTFSDIRHANDLE);
-    return TestFSDH_init(self, formatter);
-}
-
-TestFSDirHandle*
-TestFSDH_init(TestFSDirHandle *self, TestFormatter *formatter) {
-    return (TestFSDirHandle*)TestBatch_init((TestBatch*)self, 5, formatter);
+TestFSDH_new() {
+    return (TestFSDirHandle*)VTable_Make_Obj(TESTFSDIRHANDLE);
 }
 
 static void
-test_all(TestBatch *batch) {
+test_all(TestBatchRunner *runner) {
     CharBuf  *foo           = (CharBuf*)ZCB_WRAP_STR("foo", 3);
     CharBuf  *boffo         = (CharBuf*)ZCB_WRAP_STR("boffo", 5);
     CharBuf  *foo_boffo     = (CharBuf*)ZCB_WRAP_STR("foo/boffo", 9);
@@ -84,12 +78,12 @@ test_all(TestBatch *batch) {
             boffo_was_dir = FSDH_Entry_Is_Dir(dh);
         }
     }
-    TEST_INT_EQ(batch, 2, count, "correct number of entries");
-    TEST_TRUE(batch, saw_foo, "Directory was iterated over");
-    TEST_TRUE(batch, foo_was_dir,
+    TEST_INT_EQ(runner, 2, count, "correct number of entries");
+    TEST_TRUE(runner, saw_foo, "Directory was iterated over");
+    TEST_TRUE(runner, foo_was_dir,
               "Dir correctly identified by Entry_Is_Dir");
-    TEST_TRUE(batch, saw_boffo, "File was iterated over");
-    TEST_FALSE(batch, boffo_was_dir,
+    TEST_TRUE(runner, saw_boffo, "File was iterated over");
+    TEST_FALSE(runner, boffo_was_dir,
                "File correctly identified by Entry_Is_Dir");
 
     DECREF(dh);
@@ -101,9 +95,9 @@ test_all(TestBatch *batch) {
 }
 
 void
-TestFSDH_run_tests(TestFSDirHandle *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_all(batch);
+TestFSDH_run(TestFSDirHandle *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 5);
+    test_all(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFSDirHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSDirHandle.cfh b/core/Lucy/Test/Store/TestFSDirHandle.cfh
index 33ae342..69247b3 100644
--- a/core/Lucy/Test/Store/TestFSDirHandle.cfh
+++ b/core/Lucy/Test/Store/TestFSDirHandle.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestFSDirHandle cnick TestFSDH
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFSDirHandle*
-    new(TestFormatter *formatter);
-
-    inert TestFSDirHandle*
-    init(TestFSDirHandle *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFSDirHandle *self);
+    Run(TestFSDirHandle *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFSFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFileHandle.c b/core/Lucy/Test/Store/TestFSFileHandle.c
index 838d86d..d9ab78e 100644
--- a/core/Lucy/Test/Store/TestFSFileHandle.c
+++ b/core/Lucy/Test/Store/TestFSFileHandle.c
@@ -27,25 +27,19 @@
   #include <io.h> // close
 #endif
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFSFileHandle.h"
 #include "Lucy/Store/FSFileHandle.h"
 #include "Lucy/Store/FileWindow.h"
 
 TestFSFileHandle*
-TestFSFH_new(TestFormatter *formatter) {
-    TestFSFileHandle *self = (TestFSFileHandle*)VTable_Make_Obj(TESTFSFILEHANDLE);
-    return TestFSFH_init(self, formatter);
-}
-
-TestFSFileHandle*
-TestFSFH_init(TestFSFileHandle *self, TestFormatter *formatter) {
-    return (TestFSFileHandle*)TestBatch_init((TestBatch*)self, 46, formatter);
+TestFSFH_new() {
+    return (TestFSFileHandle*)VTable_Make_Obj(TESTFSFILEHANDLE);
 }
 
 static void
-test_open(TestBatch *batch) {
+test_open(TestBatchRunner *runner) {
 
     FSFileHandle *fh;
     CharBuf *test_filename = (CharBuf*)ZCB_WRAP_STR("_fstest", 7);
@@ -54,44 +48,44 @@ test_open(TestBatch *batch) {
 
     Err_set_error(NULL);
     fh = FSFH_open(test_filename, FH_READ_ONLY);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "open() with FH_READ_ONLY on non-existent file returns NULL");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "open() with FH_READ_ONLY on non-existent file sets error");
 
     Err_set_error(NULL);
     fh = FSFH_open(test_filename, FH_WRITE_ONLY);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "open() without FH_CREATE returns NULL");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "open() without FH_CREATE sets error");
 
     Err_set_error(NULL);
     fh = FSFH_open(test_filename, FH_CREATE);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "open() without FH_WRITE_ONLY returns NULL");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "open() without FH_WRITE_ONLY sets error");
 
     Err_set_error(NULL);
     fh = FSFH_open(test_filename, FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
-    TEST_TRUE(batch, fh && FSFH_Is_A(fh, FSFILEHANDLE), "open() succeeds");
-    TEST_TRUE(batch, Err_get_error() == NULL, "open() no errors");
+    TEST_TRUE(runner, fh && FSFH_Is_A(fh, FSFILEHANDLE), "open() succeeds");
+    TEST_TRUE(runner, Err_get_error() == NULL, "open() no errors");
     FSFH_Write(fh, "foo", 3);
     if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }
     DECREF(fh);
 
     Err_set_error(NULL);
     fh = FSFH_open(test_filename, FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
-    TEST_TRUE(batch, fh == NULL, "FH_EXCLUSIVE blocks open()");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, fh == NULL, "FH_EXCLUSIVE blocks open()");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "FH_EXCLUSIVE blocks open(), sets error");
 
     Err_set_error(NULL);
     fh = FSFH_open(test_filename, FH_CREATE | FH_WRITE_ONLY);
-    TEST_TRUE(batch, fh && FSFH_Is_A(fh, FSFILEHANDLE),
+    TEST_TRUE(runner, fh && FSFH_Is_A(fh, FSFILEHANDLE),
               "open() for append");
-    TEST_TRUE(batch, Err_get_error() == NULL,
+    TEST_TRUE(runner, Err_get_error() == NULL,
               "open() for append -- no errors");
     FSFH_Write(fh, "bar", 3);
     if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }
@@ -99,8 +93,8 @@ test_open(TestBatch *batch) {
 
     Err_set_error(NULL);
     fh = FSFH_open(test_filename, FH_READ_ONLY);
-    TEST_TRUE(batch, fh && FSFH_Is_A(fh, FSFILEHANDLE), "open() read only");
-    TEST_TRUE(batch, Err_get_error() == NULL,
+    TEST_TRUE(runner, fh && FSFH_Is_A(fh, FSFILEHANDLE), "open() read only");
+    TEST_TRUE(runner, Err_get_error() == NULL,
               "open() read only -- no errors");
     DECREF(fh);
 
@@ -108,7 +102,7 @@ test_open(TestBatch *batch) {
 }
 
 static void
-test_Read_Write(TestBatch *batch) {
+test_Read_Write(TestBatchRunner *runner) {
     FSFileHandle *fh;
     const char *foo = "foo";
     const char *bar = "bar";
@@ -120,16 +114,16 @@ test_Read_Write(TestBatch *batch) {
     fh = FSFH_open(test_filename,
                    FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
 
-    TEST_TRUE(batch, FSFH_Length(fh) == INT64_C(0), "Length initially 0");
-    TEST_TRUE(batch, FSFH_Write(fh, foo, 3), "Write returns success");
-    TEST_TRUE(batch, FSFH_Length(fh) == INT64_C(3), "Length after Write");
-    TEST_TRUE(batch, FSFH_Write(fh, bar, 3), "Write returns success");
-    TEST_TRUE(batch, FSFH_Length(fh) == INT64_C(6), "Length after 2 Writes");
+    TEST_TRUE(runner, FSFH_Length(fh) == INT64_C(0), "Length initially 0");
+    TEST_TRUE(runner, FSFH_Write(fh, foo, 3), "Write returns success");
+    TEST_TRUE(runner, FSFH_Length(fh) == INT64_C(3), "Length after Write");
+    TEST_TRUE(runner, FSFH_Write(fh, bar, 3), "Write returns success");
+    TEST_TRUE(runner, FSFH_Length(fh) == INT64_C(6), "Length after 2 Writes");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, FSFH_Read(fh, buf, 0, 2),
+    TEST_FALSE(runner, FSFH_Read(fh, buf, 0, 2),
                "Reading from a write-only handle returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Reading from a write-only handle sets error");
     if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }
     DECREF(fh);
@@ -138,28 +132,28 @@ test_Read_Write(TestBatch *batch) {
     Err_set_error(NULL);
     fh = FSFH_open(test_filename, FH_READ_ONLY);
 
-    TEST_TRUE(batch, FSFH_Length(fh) == INT64_C(6), "Length on Read");
-    TEST_TRUE(batch, FSFH_Read(fh, buf, 0, 6), "Read returns success");
-    TEST_TRUE(batch, strncmp(buf, "foobar", 6) == 0, "Read/Write");
-    TEST_TRUE(batch, FSFH_Read(fh, buf, 2, 3), "Read returns success");
-    TEST_TRUE(batch, strncmp(buf, "oba", 3) == 0, "Read with offset");
+    TEST_TRUE(runner, FSFH_Length(fh) == INT64_C(6), "Length on Read");
+    TEST_TRUE(runner, FSFH_Read(fh, buf, 0, 6), "Read returns success");
+    TEST_TRUE(runner, strncmp(buf, "foobar", 6) == 0, "Read/Write");
+    TEST_TRUE(runner, FSFH_Read(fh, buf, 2, 3), "Read returns success");
+    TEST_TRUE(runner, strncmp(buf, "oba", 3) == 0, "Read with offset");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, FSFH_Read(fh, buf, -1, 4),
+    TEST_FALSE(runner, FSFH_Read(fh, buf, -1, 4),
                "Read() with a negative offset returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Read() with a negative offset sets error");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, FSFH_Read(fh, buf, 6, 1),
+    TEST_FALSE(runner, FSFH_Read(fh, buf, 6, 1),
                "Read() past EOF returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Read() past EOF sets error");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, FSFH_Write(fh, foo, 3),
+    TEST_FALSE(runner, FSFH_Write(fh, foo, 3),
                "Writing to a read-only handle returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Writing to a read-only handle sets error");
 
     DECREF(fh);
@@ -167,14 +161,14 @@ test_Read_Write(TestBatch *batch) {
 }
 
 static void
-test_Close(TestBatch *batch) {
+test_Close(TestBatchRunner *runner) {
     CharBuf *test_filename = (CharBuf*)ZCB_WRAP_STR("_fstest", 7);
     FSFileHandle *fh;
 
     remove((char*)CB_Get_Ptr8(test_filename));
     fh = FSFH_open(test_filename,
                    FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
-    TEST_TRUE(batch, FSFH_Close(fh), "Close returns true for write-only");
+    TEST_TRUE(runner, FSFH_Close(fh), "Close returns true for write-only");
     DECREF(fh);
 
     // Simulate an OS error when closing the file descriptor.  This
@@ -183,29 +177,29 @@ test_Close(TestBatch *batch) {
     fh = FSFH_open(test_filename,
                    FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
 #ifdef _MSC_VER
-    SKIP(batch, "LUCY-155");
-    SKIP(batch, "LUCY-155");
+    SKIP(runner, "LUCY-155");
+    SKIP(runner, "LUCY-155");
 #else
     int saved_fd = fh->fd;
     fh->fd = -1;
     Err_set_error(NULL);
     bool result = FSFH_Close(fh);
-    TEST_FALSE(batch, result, "Failed Close() returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Failed Close() returns false");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Failed Close() sets Err_error");
     fh->fd = saved_fd;
 #endif /* _MSC_VER */
     DECREF(fh);
 
     fh = FSFH_open(test_filename, FH_READ_ONLY);
-    TEST_TRUE(batch, FSFH_Close(fh), "Close returns true for read-only");
+    TEST_TRUE(runner, FSFH_Close(fh), "Close returns true for read-only");
 
     DECREF(fh);
     remove((char*)CB_Get_Ptr8(test_filename));
 }
 
 static void
-test_Window(TestBatch *batch) {
+test_Window(TestBatchRunner *runner) {
     CharBuf *test_filename = (CharBuf*)ZCB_WRAP_STR("_fstest", 7);
     FSFileHandle *fh;
     FileWindow *window = FileWindow_new();
@@ -225,28 +219,28 @@ test_Window(TestBatch *batch) {
     if (!fh) { RETHROW(INCREF(Err_get_error())); }
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, FSFH_Window(fh, window, -1, 4),
+    TEST_FALSE(runner, FSFH_Window(fh, window, -1, 4),
                "Window() with a negative offset returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Window() with a negative offset sets error");
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, FSFH_Window(fh, window, 4000, 1000),
+    TEST_FALSE(runner, FSFH_Window(fh, window, 4000, 1000),
                "Window() past EOF returns false");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Window() past EOF sets error");
 
-    TEST_TRUE(batch, FSFH_Window(fh, window, 1021, 2),
+    TEST_TRUE(runner, FSFH_Window(fh, window, 1021, 2),
               "Window() returns true");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               strncmp(window->buf - window->offset + 1021, "oo", 2) == 0,
               "Window()");
 
-    TEST_TRUE(batch, FSFH_Release_Window(fh, window),
+    TEST_TRUE(runner, FSFH_Release_Window(fh, window),
               "Release_Window() returns true");
-    TEST_TRUE(batch, window->buf == NULL, "Release_Window() resets buf");
-    TEST_TRUE(batch, window->offset == 0, "Release_Window() resets offset");
-    TEST_TRUE(batch, window->len == 0, "Release_Window() resets len");
+    TEST_TRUE(runner, window->buf == NULL, "Release_Window() resets buf");
+    TEST_TRUE(runner, window->offset == 0, "Release_Window() resets offset");
+    TEST_TRUE(runner, window->len == 0, "Release_Window() resets len");
 
     DECREF(window);
     DECREF(fh);
@@ -254,12 +248,12 @@ test_Window(TestBatch *batch) {
 }
 
 void
-TestFSFH_run_tests(TestFSFileHandle *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_open(batch);
-    test_Read_Write(batch);
-    test_Close(batch);
-    test_Window(batch);
+TestFSFH_run(TestFSFileHandle *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 46);
+    test_open(runner);
+    test_Read_Write(runner);
+    test_Close(runner);
+    test_Window(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFSFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFileHandle.cfh b/core/Lucy/Test/Store/TestFSFileHandle.cfh
index 5eb2d86..a9676a2 100644
--- a/core/Lucy/Test/Store/TestFSFileHandle.cfh
+++ b/core/Lucy/Test/Store/TestFSFileHandle.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestFSFileHandle cnick TestFSFH
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFSFileHandle*
-    new(TestFormatter *formatter);
-
-    inert TestFSFileHandle*
-    init(TestFSFileHandle *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFSFileHandle *self);
+    Run(TestFSFileHandle *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFSFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFolder.c b/core/Lucy/Test/Store/TestFSFolder.c
index a64df50..37d4498 100644
--- a/core/Lucy/Test/Store/TestFSFolder.c
+++ b/core/Lucy/Test/Store/TestFSFolder.c
@@ -32,7 +32,7 @@
   #include <sys/stat.h>
 #endif
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFSFolder.h"
 #include "Lucy/Test/Store/TestFolderCommon.h"
@@ -50,15 +50,8 @@ S_create_test_symlinks(void);
 #endif /* CHY_HAS_WINDOWS_H */
 
 TestFSFolder*
-TestFSFolder_new(TestFormatter *formatter) {
-    TestFSFolder *self = (TestFSFolder*)VTable_Make_Obj(TESTFSFOLDER);
-    return TestFSFolder_init(self, formatter);
-}
-
-TestFSFolder*
-TestFSFolder_init(TestFSFolder *self, TestFormatter *formatter) {
-    uint32_t num_tests = TestFolderCommon_num_tests() + 9;
-    return (TestFSFolder*)TestBatch_init((TestBatch*)self, num_tests, formatter);
+TestFSFolder_new() {
+    return (TestFSFolder*)VTable_Make_Obj(TESTFSFOLDER);
 }
 
 static Folder*
@@ -84,22 +77,22 @@ S_tear_down() {
 }
 
 static void
-test_Initialize_and_Check(TestBatch *batch) {
+test_Initialize_and_Check(TestBatchRunner *runner) {
     rmdir("_fstest");
     CharBuf  *test_dir = (CharBuf*)ZCB_WRAP_STR("_fstest", 7);
     FSFolder *folder   = FSFolder_new(test_dir);
-    TEST_FALSE(batch, FSFolder_Check(folder),
+    TEST_FALSE(runner, FSFolder_Check(folder),
                "Check() returns false when folder dir doesn't exist");
     FSFolder_Initialize(folder);
-    PASS(batch, "Initialize() concludes without incident");
-    TEST_TRUE(batch, FSFolder_Check(folder),
+    PASS(runner, "Initialize() concludes without incident");
+    TEST_TRUE(runner, FSFolder_Check(folder),
               "Initialize() created dir, and now Check() succeeds");
     DECREF(folder);
     S_tear_down();
 }
 
 static void
-test_protect_symlinks(TestBatch *batch) {
+test_protect_symlinks(TestBatchRunner *runner) {
 #ifdef ENABLE_SYMLINK_TESTS
     FSFolder *folder    = (FSFolder*)S_set_up();
     CharBuf  *foo       = (CharBuf*)ZCB_WRAP_STR("foo", 3);
@@ -112,11 +105,11 @@ test_protect_symlinks(TestBatch *batch) {
     DECREF(outstream);
 
     if (!S_create_test_symlinks()) {
-        FAIL(batch, "symlink creation failed");
-        FAIL(batch, "symlink creation failed");
-        FAIL(batch, "symlink creation failed");
-        FAIL(batch, "symlink creation failed");
-        FAIL(batch, "symlink creation failed");
+        FAIL(runner, "symlink creation failed");
+        FAIL(runner, "symlink creation failed");
+        FAIL(runner, "symlink creation failed");
+        FAIL(runner, "symlink creation failed");
+        FAIL(runner, "symlink creation failed");
         // Try to clean up anyway.
         FSFolder_Delete_Tree(folder, foo);
         FSFolder_Delete_Tree(folder, bar);
@@ -130,33 +123,33 @@ test_protect_symlinks(TestBatch *batch) {
                 saw_bazooka_boffo = true;
             }
         }
-        TEST_FALSE(batch, saw_bazooka_boffo,
+        TEST_FALSE(runner, saw_bazooka_boffo,
                    "List_R() shouldn't follow symlinks");
         DECREF(list);
 
-        TEST_TRUE(batch, FSFolder_Delete_Tree(folder, bar),
+        TEST_TRUE(runner, FSFolder_Delete_Tree(folder, bar),
                   "Delete_Tree() returns true");
-        TEST_FALSE(batch, FSFolder_Exists(folder, bar),
+        TEST_FALSE(runner, FSFolder_Exists(folder, bar),
                    "Tree is really gone");
-        TEST_TRUE(batch, FSFolder_Exists(folder, foo),
+        TEST_TRUE(runner, FSFolder_Exists(folder, foo),
                   "Original folder sill there");
-        TEST_TRUE(batch, FSFolder_Exists(folder, foo_boffo),
+        TEST_TRUE(runner, FSFolder_Exists(folder, foo_boffo),
                   "Delete_Tree() did not follow directory symlink");
         FSFolder_Delete_Tree(folder, foo);
     }
     DECREF(folder);
     S_tear_down();
 #else
-    SKIP(batch, "Tests requiring symlink() disabled");
-    SKIP(batch, "Tests requiring symlink() disabled");
-    SKIP(batch, "Tests requiring symlink() disabled");
-    SKIP(batch, "Tests requiring symlink() disabled");
-    SKIP(batch, "Tests requiring symlink() disabled");
+    SKIP(runner, "Tests requiring symlink() disabled");
+    SKIP(runner, "Tests requiring symlink() disabled");
+    SKIP(runner, "Tests requiring symlink() disabled");
+    SKIP(runner, "Tests requiring symlink() disabled");
+    SKIP(runner, "Tests requiring symlink() disabled");
 #endif // ENABLE_SYMLINK_TESTS
 }
 
 void
-test_disallow_updir(TestBatch *batch) {
+test_disallow_updir(TestBatchRunner *runner) {
     FSFolder *outer_folder = (FSFolder*)S_set_up();
 
     CharBuf *foo = (CharBuf*)ZCB_WRAP_STR("foo", 3);
@@ -167,7 +160,7 @@ test_disallow_updir(TestBatch *batch) {
     CharBuf *inner_path = (CharBuf*)ZCB_WRAP_STR("_fstest/foo", 11);
     FSFolder *foo_folder = FSFolder_new(inner_path);
     CharBuf *up_bar = (CharBuf*)ZCB_WRAP_STR("../bar", 6);
-    TEST_FALSE(batch, FSFolder_Exists(foo_folder, up_bar),
+    TEST_FALSE(runner, FSFolder_Exists(foo_folder, up_bar),
                "up-dirs are inaccessible.");
 
     DECREF(foo_folder);
@@ -178,12 +171,13 @@ test_disallow_updir(TestBatch *batch) {
 }
 
 void
-TestFSFolder_run_tests(TestFSFolder *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Initialize_and_Check(batch);
-    TestFolderCommon_run_tests(batch, S_set_up, S_tear_down);
-    test_protect_symlinks(batch);
-    test_disallow_updir(batch);
+TestFSFolder_run(TestFSFolder *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self,
+                          TestFolderCommon_num_tests() + 9);
+    test_Initialize_and_Check(runner);
+    TestFolderCommon_run_tests(runner, S_set_up, S_tear_down);
+    test_protect_symlinks(runner);
+    test_disallow_updir(runner);
 }
 
 #ifdef ENABLE_SYMLINK_TESTS

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFSFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFolder.cfh b/core/Lucy/Test/Store/TestFSFolder.cfh
index f590315..bbdae58 100644
--- a/core/Lucy/Test/Store/TestFSFolder.cfh
+++ b/core/Lucy/Test/Store/TestFSFolder.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestFSFolder
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFSFolder*
-    new(TestFormatter *formatter);
-
-    inert TestFSFolder*
-    init(TestFSFolder *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFSFolder *self);
+    Run(TestFSFolder *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFileHandle.c b/core/Lucy/Test/Store/TestFileHandle.c
index 47afb43..9b3d7c6 100644
--- a/core/Lucy/Test/Store/TestFileHandle.c
+++ b/core/Lucy/Test/Store/TestFileHandle.c
@@ -20,21 +20,15 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestFileHandle.h"
 #include "Lucy/Store/FileHandle.h"
 #include "Lucy/Store/FileWindow.h"
 
 TestFileHandle*
-TestFH_new(TestFormatter *formatter) {
-    TestFileHandle *self = (TestFileHandle*)VTable_Make_Obj(TESTFILEHANDLE);
-    return TestFH_init(self, formatter);
-}
-
-TestFileHandle*
-TestFH_init(TestFileHandle *self, TestFormatter *formatter) {
-    return (TestFileHandle*)TestBatch_init((TestBatch*)self, 2, formatter);
+TestFH_new() {
+    return (TestFileHandle*)VTable_Make_Obj(TESTFILEHANDLE);
 }
 
 static void
@@ -56,14 +50,15 @@ S_new_filehandle() {
 }
 
 void
-TestFH_run_tests(TestFileHandle *self) {
-    TestBatch     *batch = (TestBatch*)self;
+TestFH_run(TestFileHandle *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 2);
+
     FileHandle    *fh    = S_new_filehandle();
     ZombieCharBuf *foo   = ZCB_WRAP_STR("foo", 3);
 
-    TEST_TRUE(batch, CB_Equals_Str(FH_Get_Path(fh), "", 0), "Get_Path");
+    TEST_TRUE(runner, CB_Equals_Str(FH_Get_Path(fh), "", 0), "Get_Path");
     FH_Set_Path(fh, (CharBuf*)foo);
-    TEST_TRUE(batch, CB_Equals(FH_Get_Path(fh), (Obj*)foo), "Set_Path");
+    TEST_TRUE(runner, CB_Equals(FH_Get_Path(fh), (Obj*)foo), "Set_Path");
 
     DECREF(fh);
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFileHandle.cfh b/core/Lucy/Test/Store/TestFileHandle.cfh
index d77eaa6..e7bd28b 100644
--- a/core/Lucy/Test/Store/TestFileHandle.cfh
+++ b/core/Lucy/Test/Store/TestFileHandle.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestFileHandle cnick TestFH
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestFileHandle*
-    new(TestFormatter *formatter);
-
-    inert TestFileHandle*
-    init(TestFileHandle *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestFileHandle *self);
+    Run(TestFileHandle *self, TestBatchRunner *runner);
 }
 
 


[lucy-commits] [09/26] git commit: refs/heads/separate-clownfish-wip2 - Move Clownfish runtime tests to a separate parcel

Posted by nw...@apache.org.
Move Clownfish runtime tests to a separate parcel

Parcel "TestClownfish", cnick "TestCfish".

There's some code duplication in Clownfish::Test and
Clownfish::TestUtils which can be addressed later.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/9f826b31
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/9f826b31
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/9f826b31

Branch: refs/heads/separate-clownfish-wip2
Commit: 9f826b31875c77f9d3756f90b380652aa19e1468
Parents: 32fe546
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 27 19:40:10 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:17 2013 +0200

----------------------------------------------------------------------
 c/t/test_lucy.c                                |    7 +-
 common/charmonizer.c                           |    8 +
 common/charmonizer.main                        |    8 +
 core/Clownfish/Test.c                          |  117 +++++
 core/Clownfish/Test.cfh                        |   42 ++
 core/Clownfish/Test/TestByteBuf.c              |  173 ++++++++
 core/Clownfish/Test/TestByteBuf.cfh            |   32 ++
 core/Clownfish/Test/TestCharBuf.c              |  442 +++++++++++++++++++
 core/Clownfish/Test/TestCharBuf.cfh            |   32 ++
 core/Clownfish/Test/TestErr.c                  |   56 +++
 core/Clownfish/Test/TestErr.cfh                |   31 ++
 core/Clownfish/Test/TestHash.c                 |  293 ++++++++++++
 core/Clownfish/Test/TestHash.cfh               |   32 ++
 core/Clownfish/Test/TestLockFreeRegistry.c     |   89 ++++
 core/Clownfish/Test/TestLockFreeRegistry.cfh   |   43 ++
 core/Clownfish/Test/TestNum.c                  |  325 ++++++++++++++
 core/Clownfish/Test/TestNum.cfh                |   32 ++
 core/Clownfish/Test/TestObj.c                  |  216 +++++++++
 core/Clownfish/Test/TestObj.cfh                |   32 ++
 core/Clownfish/Test/TestUtils.c                |  140 ++++++
 core/Clownfish/Test/TestUtils.cfh              |   71 +++
 core/Clownfish/Test/TestVArray.c               |  353 +++++++++++++++
 core/Clownfish/Test/TestVArray.cfh             |   32 ++
 core/Clownfish/Test/Util/TestAtomic.c          |   71 +++
 core/Clownfish/Test/Util/TestAtomic.cfh        |   32 ++
 core/Clownfish/Test/Util/TestMemory.c          |  124 ++++++
 core/Clownfish/Test/Util/TestMemory.cfh        |   32 ++
 core/Clownfish/Test/Util/TestNumberUtils.c     |  381 ++++++++++++++++
 core/Clownfish/Test/Util/TestNumberUtils.cfh   |   32 ++
 core/Clownfish/Test/Util/TestStringHelper.c    |  361 +++++++++++++++
 core/Clownfish/Test/Util/TestStringHelper.cfh  |   32 ++
 core/Lucy/Test.c                               |   24 -
 core/Lucy/Test/Object/TestByteBuf.c            |  168 -------
 core/Lucy/Test/Object/TestByteBuf.cfh          |   33 --
 core/Lucy/Test/Object/TestCharBuf.c            |  436 ------------------
 core/Lucy/Test/Object/TestCharBuf.cfh          |   33 --
 core/Lucy/Test/Object/TestErr.c                |   53 ---
 core/Lucy/Test/Object/TestErr.cfh              |   31 --
 core/Lucy/Test/Object/TestHash.c               |  286 ------------
 core/Lucy/Test/Object/TestHash.cfh             |   32 --
 core/Lucy/Test/Object/TestLockFreeRegistry.c   |   86 ----
 core/Lucy/Test/Object/TestLockFreeRegistry.cfh |   43 --
 core/Lucy/Test/Object/TestNum.c                |  321 --------------
 core/Lucy/Test/Object/TestNum.cfh              |   32 --
 core/Lucy/Test/Object/TestObj.c                |  211 ---------
 core/Lucy/Test/Object/TestObj.cfh              |   32 --
 core/Lucy/Test/Object/TestVArray.c             |  345 ---------------
 core/Lucy/Test/Object/TestVArray.cfh           |   32 --
 core/Lucy/Test/TestUtils.c                     |    2 +-
 core/Lucy/Test/Util/TestAtomic.c               |   68 ---
 core/Lucy/Test/Util/TestAtomic.cfh             |   32 --
 core/Lucy/Test/Util/TestMemory.c               |  121 -----
 core/Lucy/Test/Util/TestMemory.cfh             |   32 --
 core/Lucy/Test/Util/TestNumberUtils.c          |  376 ----------------
 core/Lucy/Test/Util/TestNumberUtils.cfh        |   32 --
 core/Lucy/Test/Util/TestStringHelper.c         |  354 ---------------
 core/Lucy/Test/Util/TestStringHelper.cfh       |   32 --
 core/TestClownfish.c                           |   20 +
 core/TestClownfish.cfp                         |    5 +
 perl/Build.PL                                  |    2 +-
 perl/buildlib/Lucy/Build/Binding/Misc.pm       |   33 ++-
 perl/lib/Clownfish/Test.pm                     |   25 +
 perl/t/core/016-varray.t                       |    4 +-
 perl/t/core/017-hash.t                         |    4 +-
 perl/t/core/019-obj.t                          |    4 +-
 perl/t/core/020-err.t                          |    4 +-
 perl/t/core/022-bytebuf.t                      |    4 +-
 perl/t/core/029-charbuf.t                      |    4 +-
 perl/t/core/030-number_utils.t                 |    6 +-
 perl/t/core/031-num.t                          |    4 +-
 perl/t/core/032-string_helper.t                |    6 +-
 perl/t/core/037-atomic.t                       |    4 +-
 perl/t/core/038-lock_free_registry.t           |    6 +-
 perl/t/core/039-memory.t                       |    4 +-
 74 files changed, 3782 insertions(+), 3275 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/c/t/test_lucy.c
----------------------------------------------------------------------
diff --git a/c/t/test_lucy.c b/c/t/test_lucy.c
index 709b5d1..d7ba0bb 100644
--- a/c/t/test_lucy.c
+++ b/c/t/test_lucy.c
@@ -17,17 +17,20 @@
 #include <stdlib.h>
 
 #include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Test.h"
 #include "Lucy/Test.h"
 
 int
 main() {
     cfish_TestFormatterCF *formatter;
-    bool success;
+    bool success = true;
 
+    testcfish_bootstrap_parcel();
     lucy_bootstrap_parcel();
 
     formatter = cfish_TestFormatterCF_new();
-    success = lucy_Test_run_all_batches((cfish_TestFormatter*)formatter);
+    success &= testcfish_Test_run_all_batches((cfish_TestFormatter*)formatter);
+    success &= lucy_Test_run_all_batches((cfish_TestFormatter*)formatter);
     CFISH_DECREF(formatter);
 
     return success ? EXIT_SUCCESS : EXIT_FAILURE;

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/common/charmonizer.c b/common/charmonizer.c
index 267e1a5..81daf3f 100644
--- a/common/charmonizer.c
+++ b/common/charmonizer.c
@@ -6833,6 +6833,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
     }
 
     chaz_CFlags_add_define(extra_cflags, "CFP_CFISH", NULL);
+    chaz_CFlags_add_define(extra_cflags, "CFP_TESTCFISH", NULL);
     chaz_CFlags_add_define(extra_cflags, "CFP_LUCY", NULL);
 }
 
@@ -6989,6 +6990,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeVar_append(var, scratch);
     free(scratch);
     scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
+                             "testcfish_parcel", obj_ext, NULL);
+    chaz_MakeVar_append(var, scratch);
+    free(scratch);
+    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
                              "lucy_parcel", obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
@@ -7031,6 +7036,9 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     scratch = chaz_Util_join(dir_sep, "autogen", "source", "cfish_parcel.c",
                              NULL);
     rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
+    scratch = chaz_Util_join(dir_sep, "autogen", "source",
+                             "testcfish_parcel.c", NULL);
+    rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
     free(scratch);
     scratch = chaz_Util_join(dir_sep, "autogen", "source", "lucy_parcel.c",
                              NULL);

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index d7236fb..539d0fb 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -91,6 +91,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
     }
 
     chaz_CFlags_add_define(extra_cflags, "CFP_CFISH", NULL);
+    chaz_CFlags_add_define(extra_cflags, "CFP_TESTCFISH", NULL);
     chaz_CFlags_add_define(extra_cflags, "CFP_LUCY", NULL);
 }
 
@@ -247,6 +248,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeVar_append(var, scratch);
     free(scratch);
     scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
+                             "testcfish_parcel", obj_ext, NULL);
+    chaz_MakeVar_append(var, scratch);
+    free(scratch);
+    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
                              "lucy_parcel", obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
@@ -289,6 +294,9 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     scratch = chaz_Util_join(dir_sep, "autogen", "source", "cfish_parcel.c",
                              NULL);
     rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
+    scratch = chaz_Util_join(dir_sep, "autogen", "source",
+                             "testcfish_parcel.c", NULL);
+    rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
     free(scratch);
     scratch = chaz_Util_join(dir_sep, "autogen", "source", "lucy_parcel.c",
                              NULL);

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test.c b/core/Clownfish/Test.c
new file mode 100644
index 0000000..d569e55
--- /dev/null
+++ b/core/Clownfish/Test.c
@@ -0,0 +1,117 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test.h"
+
+#include "Clownfish/Err.h"
+#include "Clownfish/Test/TestBatch.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Test/TestRunner.h"
+#include "Clownfish/VArray.h"
+
+#include "Clownfish/Test/TestByteBuf.h"
+#include "Clownfish/Test/TestCharBuf.h"
+#include "Clownfish/Test/TestErr.h"
+#include "Clownfish/Test/TestHash.h"
+#include "Clownfish/Test/TestLockFreeRegistry.h"
+#include "Clownfish/Test/TestNum.h"
+#include "Clownfish/Test/TestObj.h"
+#include "Clownfish/Test/TestVArray.h"
+#include "Clownfish/Test/Util/TestAtomic.h"
+#include "Clownfish/Test/Util/TestMemory.h"
+#include "Clownfish/Test/Util/TestNumberUtils.h"
+#include "Clownfish/Test/Util/TestStringHelper.h"
+
+static void
+S_unbuffer_stdout();
+
+static VArray*
+S_all_test_batches(TestFormatter *formatter) {
+    VArray *batches = VA_new(0);
+
+    VA_Push(batches, (Obj*)TestVArray_new(formatter));
+    VA_Push(batches, (Obj*)TestHash_new(formatter));
+    VA_Push(batches, (Obj*)TestObj_new(formatter));
+    VA_Push(batches, (Obj*)TestErr_new(formatter));
+    VA_Push(batches, (Obj*)TestBB_new(formatter));
+    VA_Push(batches, (Obj*)TestCB_new(formatter));
+    VA_Push(batches, (Obj*)TestNumUtil_new(formatter));
+    VA_Push(batches, (Obj*)TestNum_new(formatter));
+    VA_Push(batches, (Obj*)TestStrHelp_new(formatter));
+    VA_Push(batches, (Obj*)TestAtomic_new(formatter));
+    VA_Push(batches, (Obj*)TestLFReg_new(formatter));
+    VA_Push(batches, (Obj*)TestMemory_new(formatter));
+
+    return batches;
+}
+
+bool
+Test_run_batch(CharBuf *class_name, TestFormatter *formatter) {
+    S_unbuffer_stdout();
+
+    VArray   *batches = S_all_test_batches(formatter);
+    uint32_t  size    = VA_Get_Size(batches);
+
+    for (uint32_t i = 0; i < size; ++i) {
+        TestBatch *batch = (TestBatch*)VA_Fetch(batches, i);
+
+        if (CB_Equals(TestBatch_Get_Class_Name(batch), (Obj*)class_name)) {
+            bool result = TestBatch_Run(batch);
+            DECREF(batches);
+            return result;
+        }
+    }
+
+    DECREF(batches);
+    THROW(ERR, "Couldn't find test class '%o'", class_name);
+    UNREACHABLE_RETURN(bool);
+}
+
+bool
+Test_run_all_batches(TestFormatter *formatter) {
+    S_unbuffer_stdout();
+
+    TestRunner *runner  = TestRunner_new(formatter);
+    VArray     *batches = S_all_test_batches(formatter);
+    uint32_t    size    = VA_Get_Size(batches);
+
+    for (uint32_t i = 0; i < size; ++i) {
+        TestBatch *batch = (TestBatch*)VA_Fetch(batches, i);
+        TestRunner_Run_Batch(runner, batch);
+    }
+
+    bool result = TestRunner_Finish(runner);
+
+    DECREF(runner);
+    DECREF(batches);
+    return result;
+}
+
+static void
+S_unbuffer_stdout() {
+    int check_val = setvbuf(stdout, NULL, _IONBF, 0);
+    if (check_val != 0) {
+        fprintf(stderr, "Failed when trying to unbuffer stdout\n");
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test.cfh b/core/Clownfish/Test.cfh
new file mode 100644
index 0000000..4ceb429
--- /dev/null
+++ b/core/Clownfish/Test.cfh
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+/** Testing framework.
+ */
+inert class Clownfish::Test {
+    inert bool
+    run_batch(CharBuf *class_name, TestFormatter *formatter);
+
+    inert bool
+    run_all_batches(TestFormatter *formatter);
+}
+
+__C__
+#ifdef TESTCFISH_USE_SHORT_NAMES
+  #define TEST_TRUE                    cfish_TestBatch_test_true
+  #define TEST_FALSE                   cfish_TestBatch_test_false
+  #define TEST_INT_EQ                  cfish_TestBatch_test_int_equals
+  #define TEST_FLOAT_EQ                cfish_TestBatch_test_float_equals
+  #define TEST_STR_EQ                  cfish_TestBatch_test_string_equals
+  #define PASS                         cfish_TestBatch_pass
+  #define FAIL                         cfish_TestBatch_fail
+  #define SKIP                         cfish_TestBatch_skip
+#endif
+__END_C__
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestByteBuf.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestByteBuf.c b/core/Clownfish/Test/TestByteBuf.c
new file mode 100644
index 0000000..71329d7
--- /dev/null
+++ b/core/Clownfish/Test/TestByteBuf.c
@@ -0,0 +1,173 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestByteBuf.h"
+
+#include "Clownfish/ByteBuf.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/VTable.h"
+
+TestByteBuf*
+TestBB_new(TestFormatter *formatter) {
+    TestByteBuf *self = (TestByteBuf*)VTable_Make_Obj(TESTBYTEBUF);
+    return TestBB_init(self, formatter);
+}
+
+TestByteBuf*
+TestBB_init(TestByteBuf *self, TestFormatter *formatter) {
+    return (TestByteBuf*)TestBatch_init((TestBatch*)self, 22, formatter);
+}
+
+static void
+test_Equals(TestBatch *batch) {
+    ByteBuf *wanted = BB_new_bytes("foo", 4); // Include terminating NULL.
+    ByteBuf *got    = BB_new_bytes("foo", 4);
+
+    TEST_TRUE(batch, BB_Equals(wanted, (Obj*)got), "Equals");
+    TEST_INT_EQ(batch, BB_Hash_Sum(got), BB_Hash_Sum(wanted), "Hash_Sum");
+
+    TEST_TRUE(batch, BB_Equals_Bytes(got, "foo", 4), "Equals_Bytes");
+    TEST_FALSE(batch, BB_Equals_Bytes(got, "foo", 3),
+               "Equals_Bytes spoiled by different size");
+    TEST_FALSE(batch, BB_Equals_Bytes(got, "bar", 4),
+               "Equals_Bytes spoiled by different content");
+
+    BB_Set_Size(got, 3);
+    TEST_FALSE(batch, BB_Equals(wanted, (Obj*)got),
+               "Different size spoils Equals");
+    TEST_FALSE(batch, BB_Hash_Sum(got) == BB_Hash_Sum(wanted),
+               "Different size spoils Hash_Sum (probably -- at least this one)");
+
+    BB_Mimic_Bytes(got, "bar", 4);
+    TEST_INT_EQ(batch, BB_Get_Size(wanted), BB_Get_Size(got),
+                "same length");
+    TEST_FALSE(batch, BB_Equals(wanted, (Obj*)got),
+               "Different content spoils Equals");
+
+    DECREF(got);
+    DECREF(wanted);
+}
+
+static void
+test_Grow(TestBatch *batch) {
+    ByteBuf *bb = BB_new(1);
+    TEST_INT_EQ(batch, BB_Get_Capacity(bb), 8,
+                "Allocate in 8-byte increments");
+    BB_Grow(bb, 9);
+    TEST_INT_EQ(batch, BB_Get_Capacity(bb), 16,
+                "Grow in 8-byte increments");
+    DECREF(bb);
+}
+
+static void
+test_Clone(TestBatch *batch) {
+    ByteBuf *bb = BB_new_bytes("foo", 3);
+    ByteBuf *twin = BB_Clone(bb);
+    TEST_TRUE(batch, BB_Equals(bb, (Obj*)twin), "Clone");
+    DECREF(bb);
+    DECREF(twin);
+}
+
+static void
+test_compare(TestBatch *batch) {
+    ByteBuf *a = BB_new_bytes("foo\0a", 5);
+    ByteBuf *b = BB_new_bytes("foo\0b", 5);
+
+    BB_Set_Size(a, 4);
+    BB_Set_Size(b, 4);
+    TEST_INT_EQ(batch, BB_compare(&a, &b), 0,
+                "BB_compare returns 0 for equal ByteBufs");
+
+    BB_Set_Size(a, 3);
+    TEST_TRUE(batch, BB_compare(&a, &b) < 0, "shorter ByteBuf sorts first");
+
+    BB_Set_Size(a, 5);
+    BB_Set_Size(b, 5);
+    TEST_TRUE(batch, BB_compare(&a, &b) < 0,
+              "NULL doesn't interfere with BB_compare");
+
+    DECREF(a);
+    DECREF(b);
+}
+
+static void
+test_Mimic(TestBatch *batch) {
+    ByteBuf *a = BB_new_bytes("foo", 3);
+    ByteBuf *b = BB_new(0);
+
+    BB_Mimic(b, (Obj*)a);
+    TEST_TRUE(batch, BB_Equals(a, (Obj*)b), "Mimic");
+
+    BB_Mimic_Bytes(a, "bar", 4);
+    TEST_TRUE(batch, strcmp(BB_Get_Buf(a), "bar") == 0,
+              "Mimic_Bytes content");
+    TEST_INT_EQ(batch, BB_Get_Size(a), 4, "Mimic_Bytes size");
+
+    BB_Mimic(b, (Obj*)a);
+    TEST_TRUE(batch, BB_Equals(a, (Obj*)b), "Mimic");
+
+    DECREF(a);
+    DECREF(b);
+}
+
+static void
+test_Cat(TestBatch *batch) {
+    ByteBuf *wanted  = BB_new_bytes("foobar", 6);
+    ByteBuf *got     = BB_new_bytes("foo", 3);
+    ByteBuf *scratch = BB_new_bytes("bar", 3);
+
+    BB_Cat(got, scratch);
+    TEST_TRUE(batch, BB_Equals(wanted, (Obj*)got), "Cat");
+
+    BB_Mimic_Bytes(wanted, "foobarbaz", 9);
+    BB_Cat_Bytes(got, "baz", 3);
+    TEST_TRUE(batch, BB_Equals(wanted, (Obj*)got), "Cat_Bytes");
+
+    DECREF(scratch);
+    DECREF(got);
+    DECREF(wanted);
+}
+
+static void
+test_serialization(TestBatch *batch) {
+    ByteBuf *wanted = BB_new_bytes("foobar", 6);
+    ByteBuf *got    = (ByteBuf*)TestUtils_freeze_thaw((Obj*)wanted);
+    TEST_TRUE(batch, got && BB_Equals(wanted, (Obj*)got),
+              "Serialization round trip");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+void
+TestBB_run_tests(TestByteBuf *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_Equals(batch);
+    test_Grow(batch);
+    test_Clone(batch);
+    test_compare(batch);
+    test_Mimic(batch);
+    test_Cat(batch);
+    test_serialization(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestByteBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestByteBuf.cfh b/core/Clownfish/Test/TestByteBuf.cfh
new file mode 100644
index 0000000..fba607b
--- /dev/null
+++ b/core/Clownfish/Test/TestByteBuf.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::TestByteBuf cnick TestBB
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestByteBuf*
+    new(TestFormatter *formatter);
+
+    inert TestByteBuf*
+    init(TestByteBuf *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestByteBuf *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestCharBuf.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestCharBuf.c b/core/Clownfish/Test/TestCharBuf.c
new file mode 100644
index 0000000..891731c
--- /dev/null
+++ b/core/Clownfish/Test/TestCharBuf.c
@@ -0,0 +1,442 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestCharBuf.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Num.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/VTable.h"
+
+static char smiley[] = { (char)0xE2, (char)0x98, (char)0xBA, 0 };
+static uint32_t smiley_len = 3;
+
+TestCharBuf*
+TestCB_new(TestFormatter *formatter) {
+    TestCharBuf *self = (TestCharBuf*)VTable_Make_Obj(TESTCHARBUF);
+    return TestCB_init(self, formatter);
+}
+
+TestCharBuf*
+TestCB_init(TestCharBuf *self, TestFormatter *formatter) {
+    return (TestCharBuf*)TestBatch_init((TestBatch*)self, 55, formatter);
+}
+
+static CharBuf*
+S_get_cb(const char *string) {
+    return CB_new_from_utf8(string, strlen(string));
+}
+
+static void
+test_Cat(TestBatch *batch) {
+    CharBuf *wanted = CB_newf("a%s", smiley);
+    CharBuf *got    = S_get_cb("");
+
+    CB_Cat(got, wanted);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat");
+    DECREF(got);
+
+    got = S_get_cb("a");
+    CB_Cat_Char(got, 0x263A);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Char");
+    DECREF(got);
+
+    got = S_get_cb("a");
+    CB_Cat_Str(got, smiley, smiley_len);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Str");
+    DECREF(got);
+
+    got = S_get_cb("a");
+    CB_Cat_Trusted_Str(got, smiley, smiley_len);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Trusted_Str");
+    DECREF(got);
+
+    DECREF(wanted);
+}
+
+static void
+test_Mimic_and_Clone(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo");
+    CharBuf *got    = S_get_cb("bar");
+
+    CB_Mimic(got, (Obj*)wanted);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Mimic");
+    DECREF(got);
+
+    got = S_get_cb("bar");
+    CB_Mimic_Str(got, "foo", 3);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Mimic_Str");
+    DECREF(got);
+
+    got = CB_Clone(wanted);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Clone");
+    DECREF(got);
+
+    DECREF(wanted);
+}
+
+static void
+test_Find(TestBatch *batch) {
+    CharBuf *string = CB_new(10);
+    CharBuf *substring = S_get_cb("foo");
+
+    TEST_TRUE(batch, CB_Find(string, substring) == -1, "Not in empty string");
+    CB_setf(string, "foo");
+    TEST_TRUE(batch, CB_Find(string, substring) == 0, "Find complete string");
+    CB_setf(string, "afoo");
+    TEST_TRUE(batch, CB_Find(string, substring) == 1, "Find after first");
+    CB_Set_Size(string, 3);
+    TEST_TRUE(batch, CB_Find(string, substring) == -1, "Don't overrun");
+    CB_setf(string, "afood");
+    TEST_TRUE(batch, CB_Find(string, substring) == 1, "Find in middle");
+
+    DECREF(substring);
+    DECREF(string);
+}
+
+static void
+test_Code_Point_At_and_From(TestBatch *batch) {
+    uint32_t code_points[] = { 'a', 0x263A, 0x263A, 'b', 0x263A, 'c' };
+    uint32_t num_code_points = sizeof(code_points) / sizeof(uint32_t);
+    CharBuf *string = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
+    uint32_t i;
+
+    for (i = 0; i < num_code_points; i++) {
+        uint32_t from = num_code_points - i - 1;
+        TEST_INT_EQ(batch, CB_Code_Point_At(string, i), code_points[i],
+                    "Code_Point_At %ld", (long)i);
+        TEST_INT_EQ(batch, CB_Code_Point_At(string, from),
+                    code_points[from], "Code_Point_From %ld", (long)from);
+    }
+
+    DECREF(string);
+}
+
+static void
+test_SubString(TestBatch *batch) {
+    CharBuf *string = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
+    CharBuf *wanted = CB_newf("%sb%s", smiley, smiley);
+    CharBuf *got = CB_SubString(string, 2, 3);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "SubString");
+    DECREF(wanted);
+    DECREF(got);
+    DECREF(string);
+}
+
+static void
+test_Nip_and_Chop(TestBatch *batch) {
+    CharBuf *wanted;
+    CharBuf *got;
+
+    wanted = CB_newf("%sb%sc", smiley, smiley);
+    got    = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
+    CB_Nip(got, 2);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Nip");
+    DECREF(wanted);
+    DECREF(got);
+
+    wanted = CB_newf("a%s%s", smiley, smiley);
+    got    = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
+    CB_Chop(got, 3);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Chop");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+
+static void
+test_Truncate(TestBatch *batch) {
+    CharBuf *wanted = CB_newf("a%s", smiley, smiley);
+    CharBuf *got    = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
+    CB_Truncate(got, 2);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Truncate");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_Trim(TestBatch *batch) {
+    uint32_t spaces[] = {
+        ' ',    '\t',   '\r',   '\n',   0x000B, 0x000C, 0x000D, 0x0085,
+        0x00A0, 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004,
+        0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029,
+        0x202F, 0x205F, 0x3000
+    };
+    uint32_t num_spaces = sizeof(spaces) / sizeof(uint32_t);
+    uint32_t i;
+    CharBuf *got = CB_new(0);
+
+    // Surround a smiley with lots of whitespace.
+    for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
+    CB_Cat_Char(got, 0x263A);
+    for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
+
+    TEST_TRUE(batch, CB_Trim_Top(got), "Trim_Top returns true on success");
+    TEST_FALSE(batch, CB_Trim_Top(got),
+               "Trim_Top returns false on failure");
+    TEST_TRUE(batch, CB_Trim_Tail(got), "Trim_Tail returns true on success");
+    TEST_FALSE(batch, CB_Trim_Tail(got),
+               "Trim_Tail returns false on failure");
+    TEST_TRUE(batch, CB_Equals_Str(got, smiley, smiley_len),
+              "Trim_Top and Trim_Tail worked");
+
+    // Build the spacey smiley again.
+    CB_Truncate(got, 0);
+    for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
+    CB_Cat_Char(got, 0x263A);
+    for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
+
+    TEST_TRUE(batch, CB_Trim(got), "Trim returns true on success");
+    TEST_FALSE(batch, CB_Trim(got), "Trim returns false on failure");
+    TEST_TRUE(batch, CB_Equals_Str(got, smiley, smiley_len),
+              "Trim worked");
+
+    DECREF(got);
+}
+
+static void
+test_To_F64(TestBatch *batch) {
+    CharBuf *charbuf = S_get_cb("1.5");
+    double difference = 1.5 - CB_To_F64(charbuf);
+    if (difference < 0) { difference = 0 - difference; }
+    TEST_TRUE(batch, difference < 0.001, "To_F64");
+
+    CB_setf(charbuf, "-1.5");
+    difference = 1.5 + CB_To_F64(charbuf);
+    if (difference < 0) { difference = 0 - difference; }
+    TEST_TRUE(batch, difference < 0.001, "To_F64 negative");
+
+    CB_setf(charbuf, "1.59");
+    double value_full = CB_To_F64(charbuf);
+    CB_Set_Size(charbuf, 3);
+    double value_short = CB_To_F64(charbuf);
+    TEST_TRUE(batch, value_short < value_full,
+              "TO_F64 doesn't run past end of string");
+
+    DECREF(charbuf);
+}
+
+static void
+test_To_I64(TestBatch *batch) {
+    CharBuf *charbuf = S_get_cb("10");
+    TEST_TRUE(batch, CB_To_I64(charbuf) == 10, "To_I64");
+    CB_setf(charbuf, "-10");
+    TEST_TRUE(batch, CB_To_I64(charbuf) == -10, "To_I64 negative");
+    DECREF(charbuf);
+}
+
+
+static void
+test_vcatf_s(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar bizzle baz");
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %s baz", "bizzle");
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%s");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_null_string(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar [NULL] baz");
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %s baz", NULL);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%s NULL");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_cb(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar ZEKE baz");
+    CharBuf *catworthy = S_get_cb("ZEKE");
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %o baz", catworthy);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o CharBuf");
+    DECREF(catworthy);
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_obj(TestBatch *batch) {
+    CharBuf   *wanted = S_get_cb("ooga 20 booga");
+    Integer32 *i32 = Int32_new(20);
+    CharBuf   *got = S_get_cb("ooga");
+    CB_catf(got, " %o booga", i32);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o Obj");
+    DECREF(i32);
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_null_obj(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar [NULL] baz");
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %o baz", NULL);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o NULL");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_i8(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar -3 baz");
+    int8_t num = -3;
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %i8 baz", num);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%i8");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_i32(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar -100000 baz");
+    int32_t num = -100000;
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %i32 baz", num);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%i32");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_i64(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar -5000000000 baz");
+    int64_t num = INT64_C(-5000000000);
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %i64 baz", num);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%i64");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_u8(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar 3 baz");
+    uint8_t num = 3;
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %u8 baz", num);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u8");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_u32(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar 100000 baz");
+    uint32_t num = 100000;
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %u32 baz", num);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u32");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_u64(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo bar 5000000000 baz");
+    uint64_t num = UINT64_C(5000000000);
+    CharBuf *got = S_get_cb("foo ");
+    CB_catf(got, "bar %u64 baz", num);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u64");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_f64(TestBatch *batch) {
+    CharBuf *wanted;
+    char buf[64];
+    float num = 1.3f;
+    CharBuf *got = S_get_cb("foo ");
+    sprintf(buf, "foo bar %g baz", num);
+    wanted = CB_new_from_trusted_utf8(buf, strlen(buf));
+    CB_catf(got, "bar %f64 baz", num);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%f64");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_vcatf_x32(TestBatch *batch) {
+    CharBuf *wanted;
+    char buf[64];
+    unsigned long num = INT32_MAX;
+    CharBuf *got = S_get_cb("foo ");
+#if (SIZEOF_LONG == 4)
+    sprintf(buf, "foo bar %.8lx baz", num);
+#elif (SIZEOF_INT == 4)
+    sprintf(buf, "foo bar %.8x baz", (unsigned)num);
+#endif
+    wanted = CB_new_from_trusted_utf8(buf, strlen(buf));
+    CB_catf(got, "bar %x32 baz", (uint32_t)num);
+    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%x32");
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_serialization(TestBatch *batch) {
+    CharBuf *wanted = S_get_cb("foo");
+    CharBuf *got    = (CharBuf*)TestUtils_freeze_thaw((Obj*)wanted);
+    TEST_TRUE(batch, got && CB_Equals(wanted, (Obj*)got),
+              "Round trip through FREEZE/THAW");
+    DECREF(got);
+    DECREF(wanted);
+}
+
+void
+TestCB_run_tests(TestCharBuf *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_vcatf_s(batch);
+    test_vcatf_null_string(batch);
+    test_vcatf_cb(batch);
+    test_vcatf_obj(batch);
+    test_vcatf_null_obj(batch);
+    test_vcatf_i8(batch);
+    test_vcatf_i32(batch);
+    test_vcatf_i64(batch);
+    test_vcatf_u8(batch);
+    test_vcatf_u32(batch);
+    test_vcatf_u64(batch);
+    test_vcatf_f64(batch);
+    test_vcatf_x32(batch);
+    test_Cat(batch);
+    test_Mimic_and_Clone(batch);
+    test_Code_Point_At_and_From(batch);
+    test_Find(batch);
+    test_SubString(batch);
+    test_Nip_and_Chop(batch);
+    test_Truncate(batch);
+    test_Trim(batch);
+    test_To_F64(batch);
+    test_To_I64(batch);
+    test_serialization(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestCharBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestCharBuf.cfh b/core/Clownfish/Test/TestCharBuf.cfh
new file mode 100644
index 0000000..1ecedcc
--- /dev/null
+++ b/core/Clownfish/Test/TestCharBuf.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::TestCharBuf cnick TestCB
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestCharBuf*
+    new(TestFormatter *formatter);
+
+    inert TestCharBuf*
+    init(TestCharBuf *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestCharBuf *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestErr.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestErr.c b/core/Clownfish/Test/TestErr.c
new file mode 100644
index 0000000..c6b0869
--- /dev/null
+++ b/core/Clownfish/Test/TestErr.c
@@ -0,0 +1,56 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestErr.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/VTable.h"
+
+TestErr*
+TestErr_new(TestFormatter *formatter) {
+    TestErr *self = (TestErr*)VTable_Make_Obj(TESTERR);
+    return TestErr_init(self, formatter);
+}
+
+TestErr*
+TestErr_init(TestErr *self, TestFormatter *formatter) {
+    return (TestErr*)TestBatch_init((TestBatch*)self, 1, formatter);
+}
+
+static void
+test_To_String(TestBatch *batch) {
+    CharBuf *message = CB_newf("oops");
+    Err *error = Err_new(message);
+    CharBuf *string = Err_To_String(error);
+    TEST_TRUE(batch, CB_Equals(message, (Obj*)string),
+              "Stringifies as message");
+    DECREF(string);
+    DECREF(error);
+}
+
+void
+TestErr_run_tests(TestErr *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_To_String(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestErr.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestErr.cfh b/core/Clownfish/Test/TestErr.cfh
new file mode 100644
index 0000000..1366e7e
--- /dev/null
+++ b/core/Clownfish/Test/TestErr.cfh
@@ -0,0 +1,31 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::TestErr
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestErr*
+    new(TestFormatter *formatter);
+
+    inert TestErr*
+    init(TestErr *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestErr *self);
+}
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestHash.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestHash.c b/core/Clownfish/Test/TestHash.c
new file mode 100644
index 0000000..773a6f8
--- /dev/null
+++ b/core/Clownfish/Test/TestHash.c
@@ -0,0 +1,293 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestHash.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Hash.h"
+#include "Clownfish/Num.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/VArray.h"
+#include "Clownfish/VTable.h"
+
+TestHash*
+TestHash_new(TestFormatter *formatter) {
+    TestHash *self = (TestHash*)VTable_Make_Obj(TESTHASH);
+    return TestHash_init(self, formatter);
+}
+
+TestHash*
+TestHash_init(TestHash *self, TestFormatter *formatter) {
+    return (TestHash*)TestBatch_init((TestBatch*)self, 29, formatter);
+}
+
+static void
+test_Equals(TestBatch *batch) {
+    Hash *hash  = Hash_new(0);
+    Hash *other = Hash_new(0);
+    ZombieCharBuf *stuff = ZCB_WRAP_STR("stuff", 5);
+
+    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)other),
+              "Empty hashes are equal");
+
+    Hash_Store_Str(hash, "foo", 3, (Obj*)CFISH_TRUE);
+    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)other),
+               "Add one pair and Equals returns false");
+
+    Hash_Store_Str(other, "foo", 3, (Obj*)CFISH_TRUE);
+    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)other),
+              "Add a matching pair and Equals returns true");
+
+    Hash_Store_Str(other, "foo", 3, INCREF(stuff));
+    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)other),
+               "Non-matching value spoils Equals");
+
+    DECREF(hash);
+    DECREF(other);
+}
+
+static void
+test_Store_and_Fetch(TestBatch *batch) {
+    Hash          *hash         = Hash_new(100);
+    Hash          *dupe         = Hash_new(100);
+    const uint32_t starting_cap = Hash_Get_Capacity(hash);
+    VArray        *expected     = VA_new(100);
+    VArray        *got          = VA_new(100);
+    ZombieCharBuf *twenty       = ZCB_WRAP_STR("20", 2);
+    ZombieCharBuf *forty        = ZCB_WRAP_STR("40", 2);
+    ZombieCharBuf *foo          = ZCB_WRAP_STR("foo", 3);
+
+    for (int32_t i = 0; i < 100; i++) {
+        CharBuf *cb = CB_newf("%i32", i);
+        Hash_Store(hash, (Obj*)cb, (Obj*)cb);
+        Hash_Store(dupe, (Obj*)cb, INCREF(cb));
+        VA_Push(expected, INCREF(cb));
+    }
+    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)dupe), "Equals");
+
+    TEST_INT_EQ(batch, Hash_Get_Capacity(hash), starting_cap,
+                "Initial capacity sufficient (no rebuilds)");
+
+    for (int32_t i = 0; i < 100; i++) {
+        Obj *key  = VA_Fetch(expected, i);
+        Obj *elem = Hash_Fetch(hash, key);
+        VA_Push(got, (Obj*)INCREF(elem));
+    }
+
+    TEST_TRUE(batch, VA_Equals(got, (Obj*)expected),
+              "basic Store and Fetch");
+    TEST_INT_EQ(batch, Hash_Get_Size(hash), 100,
+                "size incremented properly by Hash_Store");
+
+    TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)foo) == NULL,
+              "Fetch against non-existent key returns NULL");
+
+    Hash_Store(hash, (Obj*)forty, INCREF(foo));
+    TEST_TRUE(batch, ZCB_Equals(foo, Hash_Fetch(hash, (Obj*)forty)),
+              "Hash_Store replaces existing value");
+    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)dupe),
+               "replacement value spoils equals");
+    TEST_INT_EQ(batch, Hash_Get_Size(hash), 100,
+                "size unaffected after value replaced");
+
+    TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == (Obj*)foo,
+              "Delete returns value");
+    DECREF(foo);
+    TEST_INT_EQ(batch, Hash_Get_Size(hash), 99,
+                "size decremented by successful Delete");
+    TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == NULL,
+              "Delete returns NULL when key not found");
+    TEST_INT_EQ(batch, Hash_Get_Size(hash), 99,
+                "size not decremented by unsuccessful Delete");
+    DECREF(Hash_Delete(dupe, (Obj*)forty));
+    TEST_TRUE(batch, VA_Equals(got, (Obj*)expected), "Equals after Delete");
+
+    Hash_Clear(hash);
+    TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)twenty) == NULL, "Clear");
+    TEST_TRUE(batch, Hash_Get_Size(hash) == 0, "size is 0 after Clear");
+
+    DECREF(hash);
+    DECREF(dupe);
+    DECREF(got);
+    DECREF(expected);
+}
+
+static void
+test_Keys_Values_Iter(TestBatch *batch) {
+    Hash     *hash     = Hash_new(0); // trigger multiple rebuilds.
+    VArray   *expected = VA_new(100);
+    VArray   *keys;
+    VArray   *values;
+
+    for (uint32_t i = 0; i < 500; i++) {
+        CharBuf *cb = CB_newf("%u32", i);
+        Hash_Store(hash, (Obj*)cb, (Obj*)cb);
+        VA_Push(expected, INCREF(cb));
+    }
+
+    VA_Sort(expected, NULL, NULL);
+
+    keys   = Hash_Keys(hash);
+    values = Hash_Values(hash);
+    VA_Sort(keys, NULL, NULL);
+    VA_Sort(values, NULL, NULL);
+    TEST_TRUE(batch, VA_Equals(keys, (Obj*)expected), "Keys");
+    TEST_TRUE(batch, VA_Equals(values, (Obj*)expected), "Values");
+    VA_Clear(keys);
+    VA_Clear(values);
+
+    {
+        Obj *key;
+        Obj *value;
+        Hash_Iterate(hash);
+        while (Hash_Next(hash, &key, &value)) {
+            VA_Push(keys, INCREF(key));
+            VA_Push(values, INCREF(value));
+        }
+    }
+
+    VA_Sort(keys, NULL, NULL);
+    VA_Sort(values, NULL, NULL);
+    TEST_TRUE(batch, VA_Equals(keys, (Obj*)expected), "Keys from Iter");
+    TEST_TRUE(batch, VA_Equals(values, (Obj*)expected), "Values from Iter");
+
+    {
+        ZombieCharBuf *forty = ZCB_WRAP_STR("40", 2);
+        ZombieCharBuf *nope  = ZCB_WRAP_STR("nope", 4);
+        Obj *key = Hash_Find_Key(hash, (Obj*)forty, ZCB_Hash_Sum(forty));
+        TEST_TRUE(batch, Obj_Equals(key, (Obj*)forty), "Find_Key");
+        key = Hash_Find_Key(hash, (Obj*)nope, ZCB_Hash_Sum(nope)),
+        TEST_TRUE(batch, key == NULL,
+                  "Find_Key returns NULL for non-existent key");
+    }
+
+    DECREF(hash);
+    DECREF(expected);
+    DECREF(keys);
+    DECREF(values);
+}
+
+static void
+test_Dump_and_Load(TestBatch *batch) {
+    Hash *hash = Hash_new(0);
+    Obj  *dump;
+    Hash *loaded;
+
+    Hash_Store_Str(hash, "foo", 3,
+                   (Obj*)CB_new_from_trusted_utf8("foo", 3));
+    dump = (Obj*)Hash_Dump(hash);
+    loaded = (Hash*)Obj_Load(dump, dump);
+    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)loaded),
+              "Dump => Load round trip");
+    DECREF(dump);
+    DECREF(loaded);
+
+    /* TODO: Fix Hash_Load().
+
+    Hash_Store_Str(hash, "_class", 6,
+        (Obj*)CB_new_from_trusted_utf8("not_a_class", 11));
+    dump = (Obj*)Hash_Dump(hash);
+    loaded = (Hash*)Obj_Load(dump, dump);
+
+    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)loaded),
+              "Load still works with _class if it's not a real class");
+    DECREF(dump);
+    DECREF(loaded);
+
+    */
+
+    DECREF(hash);
+}
+
+static void
+test_serialization(TestBatch *batch) {
+    Hash  *wanted = Hash_new(0);
+    Hash  *got;
+
+    for (uint32_t i = 0; i < 10; i++) {
+        CharBuf *cb = TestUtils_random_string(rand() % 1200);
+        Integer32 *num = Int32_new(i);
+        Hash_Store(wanted, (Obj*)cb, (Obj*)num);
+        Hash_Store(wanted, (Obj*)num, (Obj*)cb);
+    }
+
+    got = (Hash*)TestUtils_freeze_thaw((Obj*)wanted);
+    TEST_TRUE(batch, got && Hash_Equals(wanted, (Obj*)got),
+              "Round trip through serialization.");
+
+    DECREF(got);
+    DECREF(wanted);
+}
+
+static void
+test_stress(TestBatch *batch) {
+    Hash     *hash     = Hash_new(0); // trigger multiple rebuilds.
+    VArray   *expected = VA_new(1000);
+    VArray   *keys;
+    VArray   *values;
+
+    for (uint32_t i = 0; i < 1000; i++) {
+        CharBuf *cb = TestUtils_random_string(rand() % 1200);
+        while (Hash_Fetch(hash, (Obj*)cb)) {
+            DECREF(cb);
+            cb = TestUtils_random_string(rand() % 1200);
+        }
+        Hash_Store(hash, (Obj*)cb, (Obj*)cb);
+        VA_Push(expected, INCREF(cb));
+    }
+
+    VA_Sort(expected, NULL, NULL);
+
+    // Overwrite for good measure.
+    for (uint32_t i = 0; i < 1000; i++) {
+        CharBuf *cb = (CharBuf*)VA_Fetch(expected, i);
+        Hash_Store(hash, (Obj*)cb, INCREF(cb));
+    }
+
+    keys   = Hash_Keys(hash);
+    values = Hash_Values(hash);
+    VA_Sort(keys, NULL, NULL);
+    VA_Sort(values, NULL, NULL);
+    TEST_TRUE(batch, VA_Equals(keys, (Obj*)expected), "stress Keys");
+    TEST_TRUE(batch, VA_Equals(values, (Obj*)expected), "stress Values");
+
+    DECREF(keys);
+    DECREF(values);
+    DECREF(expected);
+    DECREF(hash);
+}
+
+void
+TestHash_run_tests(TestHash *self) {
+    TestBatch *batch = (TestBatch*)self;
+    srand((unsigned int)time((time_t*)NULL));
+    test_Equals(batch);
+    test_Store_and_Fetch(batch);
+    test_Keys_Values_Iter(batch);
+    test_Dump_and_Load(batch);
+    test_serialization(batch);
+    test_stress(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestHash.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestHash.cfh b/core/Clownfish/Test/TestHash.cfh
new file mode 100644
index 0000000..ed5e548
--- /dev/null
+++ b/core/Clownfish/Test/TestHash.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::TestHash
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestHash*
+    new(TestFormatter *formatter);
+
+    inert TestHash*
+    init(TestHash *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestHash *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestLockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestLockFreeRegistry.c b/core/Clownfish/Test/TestLockFreeRegistry.c
new file mode 100644
index 0000000..035bd77
--- /dev/null
+++ b/core/Clownfish/Test/TestLockFreeRegistry.c
@@ -0,0 +1,89 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+
+#define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestLockFreeRegistry.h"
+
+#include "Clownfish/LockFreeRegistry.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/VTable.h"
+
+TestLockFreeRegistry*
+TestLFReg_new(TestFormatter *formatter) {
+    TestLockFreeRegistry *self = (TestLockFreeRegistry*)VTable_Make_Obj(TESTLOCKFREEREGISTRY);
+    return TestLFReg_init(self, formatter);
+}
+
+TestLockFreeRegistry*
+TestLFReg_init(TestLockFreeRegistry *self, TestFormatter *formatter) {
+    return (TestLockFreeRegistry*)TestBatch_init((TestBatch*)self, 6, formatter);
+}
+
+StupidHashCharBuf*
+StupidHashCharBuf_new(const char *text) {
+    return (StupidHashCharBuf*)CB_new_from_utf8(text, strlen(text));
+}
+
+int32_t
+StupidHashCharBuf_hash_sum(StupidHashCharBuf *self) {
+    UNUSED_VAR(self);
+    return 1;
+}
+
+static void
+test_all(TestBatch *batch) {
+    LockFreeRegistry *registry = LFReg_new(10);
+    StupidHashCharBuf *foo = StupidHashCharBuf_new("foo");
+    StupidHashCharBuf *bar = StupidHashCharBuf_new("bar");
+    StupidHashCharBuf *baz = StupidHashCharBuf_new("baz");
+    StupidHashCharBuf *foo_dupe = StupidHashCharBuf_new("foo");
+
+    TEST_TRUE(batch, LFReg_Register(registry, (Obj*)foo, (Obj*)foo),
+              "Register() returns true on success");
+    TEST_FALSE(batch,
+               LFReg_Register(registry, (Obj*)foo_dupe, (Obj*)foo_dupe),
+               "Can't Register() keys that test equal");
+
+    TEST_TRUE(batch, LFReg_Register(registry, (Obj*)bar, (Obj*)bar),
+              "Register() key with the same Hash_Sum but that isn't Equal");
+
+    TEST_TRUE(batch, LFReg_Fetch(registry, (Obj*)foo_dupe) == (Obj*)foo,
+              "Fetch()");
+    TEST_TRUE(batch, LFReg_Fetch(registry, (Obj*)bar) == (Obj*)bar,
+              "Fetch() again");
+    TEST_TRUE(batch, LFReg_Fetch(registry, (Obj*)baz) == NULL,
+              "Fetch() non-existent key returns NULL");
+
+    DECREF(foo_dupe);
+    DECREF(baz);
+    DECREF(bar);
+    DECREF(foo);
+    DECREF(registry);
+}
+
+void
+TestLFReg_run_tests(TestLockFreeRegistry *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_all(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestLockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestLockFreeRegistry.cfh b/core/Clownfish/Test/TestLockFreeRegistry.cfh
new file mode 100644
index 0000000..b2c7d36
--- /dev/null
+++ b/core/Clownfish/Test/TestLockFreeRegistry.cfh
@@ -0,0 +1,43 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::TestLockFreeRegistry cnick TestLFReg
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestLockFreeRegistry*
+    new(TestFormatter *formatter);
+
+    inert TestLockFreeRegistry*
+    init(TestLockFreeRegistry *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestLockFreeRegistry *self);
+}
+
+/** Private test-only class for stressing LockFreeRegistry.
+ */
+class Lucy::Test::Object::StupidHashCharBuf inherits Clownfish::CharBuf {
+    inert incremented StupidHashCharBuf*
+    new(const char *text);
+
+    /** Always returns 1, guaranteeing collisions. */
+    public int32_t
+    Hash_Sum(StupidHashCharBuf *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestNum.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestNum.c b/core/Clownfish/Test/TestNum.c
new file mode 100644
index 0000000..1f01a61
--- /dev/null
+++ b/core/Clownfish/Test/TestNum.c
@@ -0,0 +1,325 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestNum.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Num.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/VTable.h"
+
+TestNum*
+TestNum_new(TestFormatter *formatter) {
+    TestNum *self = (TestNum*)VTable_Make_Obj(TESTNUM);
+    return TestNum_init(self, formatter);
+}
+
+TestNum*
+TestNum_init(TestNum *self, TestFormatter *formatter) {
+    return (TestNum*)TestBatch_init((TestBatch*)self, 58, formatter);
+}
+
+static void
+test_To_String(TestBatch *batch) {
+    Float32   *f32 = Float32_new(1.33f);
+    Float64   *f64 = Float64_new(1.33);
+    Integer32 *i32 = Int32_new(INT32_MAX);
+    Integer64 *i64 = Int64_new(INT64_MAX);
+    CharBuf *f32_string = Float32_To_String(f32);
+    CharBuf *f64_string = Float64_To_String(f64);
+    CharBuf *i32_string = Int32_To_String(i32);
+    CharBuf *i64_string = Int64_To_String(i64);
+    CharBuf *true_string  = Bool_To_String(CFISH_TRUE);
+    CharBuf *false_string = Bool_To_String(CFISH_FALSE);
+
+    TEST_TRUE(batch, CB_Starts_With_Str(f32_string, "1.3", 3),
+              "Float32_To_String");
+    TEST_TRUE(batch, CB_Starts_With_Str(f64_string, "1.3", 3),
+              "Float64_To_String");
+    TEST_TRUE(batch, CB_Equals_Str(i32_string, "2147483647", 10),
+              "Int32_To_String");
+    TEST_TRUE(batch, CB_Equals_Str(i64_string, "9223372036854775807", 19),
+              "Int64_To_String");
+    TEST_TRUE(batch, CB_Equals_Str(true_string, "true", 4),
+              "Bool_To_String [true]");
+    TEST_TRUE(batch, CB_Equals_Str(false_string, "false", 5),
+              "Bool_To_String [false]");
+
+    DECREF(false_string);
+    DECREF(true_string);
+    DECREF(i64_string);
+    DECREF(i32_string);
+    DECREF(f64_string);
+    DECREF(f32_string);
+    DECREF(i64);
+    DECREF(i32);
+    DECREF(f64);
+    DECREF(f32);
+}
+
+static void
+test_accessors(TestBatch *batch) {
+    Float32   *f32 = Float32_new(1.0);
+    Float64   *f64 = Float64_new(1.0);
+    Integer32 *i32 = Int32_new(1);
+    Integer64 *i64 = Int64_new(1);
+    float  wanted32 = 1.33f;
+    double wanted64 = 1.33;
+    float  got32;
+    double got64;
+
+    Float32_Set_Value(f32, 1.33f);
+    TEST_FLOAT_EQ(batch, Float32_Get_Value(f32), 1.33f,
+                  "F32 Set_Value Get_Value");
+
+    Float64_Set_Value(f64, 1.33);
+    got64 = Float64_Get_Value(f64);
+    TEST_TRUE(batch, *(int64_t*)&got64 == *(int64_t*)&wanted64,
+              "F64 Set_Value Get_Value");
+
+    TEST_TRUE(batch, Float32_To_I64(f32) == 1, "Float32_To_I64");
+    TEST_TRUE(batch, Float64_To_I64(f64) == 1, "Float64_To_I64");
+
+    got32 = (float)Float32_To_F64(f32);
+    TEST_TRUE(batch, *(int32_t*)&got32 == *(int32_t*)&wanted32,
+              "Float32_To_F64");
+
+    got64 = Float64_To_F64(f64);
+    TEST_TRUE(batch, *(int64_t*)&got64 == *(int64_t*)&wanted64,
+              "Float64_To_F64");
+
+    Int32_Set_Value(i32, INT32_MIN);
+    TEST_INT_EQ(batch, Int32_Get_Value(i32), INT32_MIN,
+                "I32 Set_Value Get_Value");
+
+    Int64_Set_Value(i64, INT64_MIN);
+    TEST_TRUE(batch, Int64_Get_Value(i64) == INT64_MIN,
+              "I64 Set_Value Get_Value");
+
+    Int32_Set_Value(i32, -1);
+    Int64_Set_Value(i64, -1);
+    TEST_TRUE(batch, Int32_To_F64(i32) == -1, "Int32_To_F64");
+    TEST_TRUE(batch, Int64_To_F64(i64) == -1, "Int64_To_F64");
+
+    TEST_INT_EQ(batch, Bool_Get_Value(CFISH_TRUE), true,
+                "Bool_Get_Value [true]");
+    TEST_INT_EQ(batch, Bool_Get_Value(CFISH_FALSE), false,
+                "Bool_Get_Value [false]");
+    TEST_TRUE(batch, Bool_To_I64(CFISH_TRUE) == true,
+              "Bool_To_I64 [true]");
+    TEST_TRUE(batch, Bool_To_I64(CFISH_FALSE) == false,
+              "Bool_To_I64 [false]");
+    TEST_TRUE(batch, Bool_To_F64(CFISH_TRUE) == 1.0,
+              "Bool_To_F64 [true]");
+    TEST_TRUE(batch, Bool_To_F64(CFISH_FALSE) == 0.0,
+              "Bool_To_F64 [false]");
+
+    DECREF(i64);
+    DECREF(i32);
+    DECREF(f64);
+    DECREF(f32);
+}
+
+static void
+test_Equals_and_Compare_To(TestBatch *batch) {
+    Float32   *f32 = Float32_new(1.0);
+    Float64   *f64 = Float64_new(1.0);
+    Integer32 *i32 = Int32_new(INT32_MAX);
+    Integer64 *i64 = Int64_new(INT64_MAX);
+
+    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)f64) == 0,
+              "F32_Compare_To equal");
+    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f64),
+              "F32_Equals equal");
+
+    Float64_Set_Value(f64, 2.0);
+    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)f64) < 0,
+              "F32_Compare_To less than");
+    TEST_FALSE(batch, Float32_Equals(f32, (Obj*)f64),
+               "F32_Equals less than");
+
+    Float64_Set_Value(f64, 0.0);
+    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)f64) > 0,
+              "F32_Compare_To greater than");
+    TEST_FALSE(batch, Float32_Equals(f32, (Obj*)f64),
+               "F32_Equals greater than");
+
+    Float64_Set_Value(f64, 1.0);
+    Float32_Set_Value(f32, 1.0);
+    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)f32) == 0,
+              "F64_Compare_To equal");
+    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f32),
+              "F64_Equals equal");
+
+    Float32_Set_Value(f32, 2.0);
+    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)f32) < 0,
+              "F64_Compare_To less than");
+    TEST_FALSE(batch, Float64_Equals(f64, (Obj*)f32),
+               "F64_Equals less than");
+
+    Float32_Set_Value(f32, 0.0);
+    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)f32) > 0,
+              "F64_Compare_To greater than");
+    TEST_FALSE(batch, Float64_Equals(f64, (Obj*)f32),
+               "F64_Equals greater than");
+
+    Float64_Set_Value(f64, INT64_MAX * 2.0);
+    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)i64) > 0,
+              "Float64 comparison to Integer64");
+    TEST_TRUE(batch, Int64_Compare_To(i64, (Obj*)f64) < 0,
+              "Integer64 comparison to Float64");
+
+    Float32_Set_Value(f32, INT32_MAX * 2.0f);
+    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)i32) > 0,
+              "Float32 comparison to Integer32");
+    TEST_TRUE(batch, Int32_Compare_To(i32, (Obj*)f32) < 0,
+              "Integer32 comparison to Float32");
+
+    Int64_Set_Value(i64, INT64_C(0x6666666666666666));
+    Integer64 *i64_copy = Int64_new(INT64_C(0x6666666666666666));
+    TEST_TRUE(batch, Int64_Compare_To(i64, (Obj*)i64_copy) == 0,
+              "Integer64 comparison to same number");
+
+    TEST_TRUE(batch, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_TRUE),
+              "CFISH_TRUE Equals itself");
+    TEST_TRUE(batch, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_FALSE),
+              "CFISH_FALSE Equals itself");
+    TEST_FALSE(batch, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_TRUE),
+               "CFISH_FALSE not Equals CFISH_TRUE ");
+    TEST_FALSE(batch, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_FALSE),
+               "CFISH_TRUE not Equals CFISH_FALSE ");
+    TEST_FALSE(batch, Bool_Equals(CFISH_TRUE, (Obj*)CHARBUF),
+               "CFISH_TRUE not Equals random other object ");
+
+    DECREF(i64_copy);
+    DECREF(i64);
+    DECREF(i32);
+    DECREF(f64);
+    DECREF(f32);
+}
+
+static void
+test_Clone(TestBatch *batch) {
+    Float32   *f32 = Float32_new(1.33f);
+    Float64   *f64 = Float64_new(1.33);
+    Integer32 *i32 = Int32_new(INT32_MAX);
+    Integer64 *i64 = Int64_new(INT64_MAX);
+    Float32   *f32_dupe = Float32_Clone(f32);
+    Float64   *f64_dupe = Float64_Clone(f64);
+    Integer32 *i32_dupe = Int32_Clone(i32);
+    Integer64 *i64_dupe = Int64_Clone(i64);
+    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f32_dupe),
+              "Float32 Clone");
+    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f64_dupe),
+              "Float64 Clone");
+    TEST_TRUE(batch, Int32_Equals(i32, (Obj*)i32_dupe),
+              "Integer32 Clone");
+    TEST_TRUE(batch, Int64_Equals(i64, (Obj*)i64_dupe),
+              "Integer64 Clone");
+    TEST_TRUE(batch, Bool_Equals(CFISH_TRUE, (Obj*)Bool_Clone(CFISH_TRUE)),
+              "BoolNum Clone");
+    DECREF(i64_dupe);
+    DECREF(i32_dupe);
+    DECREF(f64_dupe);
+    DECREF(f32_dupe);
+    DECREF(i64);
+    DECREF(i32);
+    DECREF(f64);
+    DECREF(f32);
+}
+
+static void
+test_Mimic(TestBatch *batch) {
+    Float32   *f32 = Float32_new(1.33f);
+    Float64   *f64 = Float64_new(1.33);
+    Integer32 *i32 = Int32_new(INT32_MAX);
+    Integer64 *i64 = Int64_new(INT64_MAX);
+    Float32   *f32_dupe = Float32_new(0.0f);
+    Float64   *f64_dupe = Float64_new(0.0);
+    Integer32 *i32_dupe = Int32_new(0);
+    Integer64 *i64_dupe = Int64_new(0);
+    Float32_Mimic(f32_dupe, (Obj*)f32);
+    Float64_Mimic(f64_dupe, (Obj*)f64);
+    Int32_Mimic(i32_dupe, (Obj*)i32);
+    Int64_Mimic(i64_dupe, (Obj*)i64);
+    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f32_dupe),
+              "Float32 Mimic");
+    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f64_dupe),
+              "Float64 Mimic");
+    TEST_TRUE(batch, Int32_Equals(i32, (Obj*)i32_dupe),
+              "Integer32 Mimic");
+    TEST_TRUE(batch, Int64_Equals(i64, (Obj*)i64_dupe),
+              "Integer64 Mimic");
+    DECREF(i64_dupe);
+    DECREF(i32_dupe);
+    DECREF(f64_dupe);
+    DECREF(f32_dupe);
+    DECREF(i64);
+    DECREF(i32);
+    DECREF(f64);
+    DECREF(f32);
+}
+
+static void
+test_serialization(TestBatch *batch) {
+    Float32   *f32 = Float32_new(1.33f);
+    Float64   *f64 = Float64_new(1.33);
+    Integer32 *i32 = Int32_new(-1);
+    Integer64 *i64 = Int64_new(-1);
+    Float32   *f32_thaw = (Float32*)TestUtils_freeze_thaw((Obj*)f32);
+    Float64   *f64_thaw = (Float64*)TestUtils_freeze_thaw((Obj*)f64);
+    Integer32 *i32_thaw = (Integer32*)TestUtils_freeze_thaw((Obj*)i32);
+    Integer64 *i64_thaw = (Integer64*)TestUtils_freeze_thaw((Obj*)i64);
+    BoolNum   *true_thaw = (BoolNum*)TestUtils_freeze_thaw((Obj*)CFISH_TRUE);
+
+    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f32_thaw),
+              "Float32 freeze/thaw");
+    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f64_thaw),
+              "Float64 freeze/thaw");
+    TEST_TRUE(batch, Int32_Equals(i32, (Obj*)i32_thaw),
+              "Integer32 freeze/thaw");
+    TEST_TRUE(batch, Int64_Equals(i64, (Obj*)i64_thaw),
+              "Integer64 freeze/thaw");
+    TEST_TRUE(batch, Bool_Equals(CFISH_TRUE, (Obj*)true_thaw),
+              "BoolNum freeze/thaw");
+
+    DECREF(i64_thaw);
+    DECREF(i32_thaw);
+    DECREF(f64_thaw);
+    DECREF(f32_thaw);
+    DECREF(i64);
+    DECREF(i32);
+    DECREF(f64);
+    DECREF(f32);
+}
+
+void
+TestNum_run_tests(TestNum *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_To_String(batch);
+    test_accessors(batch);
+    test_Equals_and_Compare_To(batch);
+    test_Clone(batch);
+    test_Mimic(batch);
+    test_serialization(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestNum.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestNum.cfh b/core/Clownfish/Test/TestNum.cfh
new file mode 100644
index 0000000..b6d1035
--- /dev/null
+++ b/core/Clownfish/Test/TestNum.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::TestNum
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestNum*
+    new(TestFormatter *formatter);
+
+    inert TestNum*
+    init(TestNum *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestNum *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestObj.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestObj.c b/core/Clownfish/Test/TestObj.c
new file mode 100644
index 0000000..fa0a80b
--- /dev/null
+++ b/core/Clownfish/Test/TestObj.c
@@ -0,0 +1,216 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestObj.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/VTable.h"
+
+TestObj*
+TestObj_new(TestFormatter *formatter) {
+    TestObj *self = (TestObj*)VTable_Make_Obj(TESTOBJ);
+    return TestObj_init(self, formatter);
+}
+
+TestObj*
+TestObj_init(TestObj *self, TestFormatter *formatter) {
+    return (TestObj*)TestBatch_init((TestBatch*)self, 20, formatter);
+}
+
+static Obj*
+S_new_testobj() {
+    ZombieCharBuf *klass = ZCB_WRAP_STR("TestObj", 7);
+    Obj *obj;
+    VTable *vtable = VTable_fetch_vtable((CharBuf*)klass);
+    if (!vtable) {
+        vtable = VTable_singleton((CharBuf*)klass, OBJ);
+    }
+    obj = VTable_Make_Obj(vtable);
+    return Obj_init(obj);
+}
+
+static void
+test_refcounts(TestBatch *batch) {
+    Obj *obj = S_new_testobj();
+
+    TEST_INT_EQ(batch, Obj_Get_RefCount(obj), 1,
+                "Correct starting refcount");
+
+    Obj_Inc_RefCount(obj);
+    TEST_INT_EQ(batch, Obj_Get_RefCount(obj), 2, "Inc_RefCount");
+
+    Obj_Dec_RefCount(obj);
+    TEST_INT_EQ(batch, Obj_Get_RefCount(obj), 1, "Dec_RefCount");
+
+    DECREF(obj);
+}
+
+static void
+test_To_String(TestBatch *batch) {
+    Obj *testobj = S_new_testobj();
+    CharBuf *string = Obj_To_String(testobj);
+    ZombieCharBuf *temp = ZCB_WRAP(string);
+    while (ZCB_Get_Size(temp)) {
+        if (ZCB_Starts_With_Str(temp, "TestObj", 7)) { break; }
+        ZCB_Nip_One(temp);
+    }
+    TEST_TRUE(batch, ZCB_Starts_With_Str(temp, "TestObj", 7), "To_String");
+    DECREF(string);
+    DECREF(testobj);
+}
+
+static void
+test_Dump(TestBatch *batch) {
+    Obj *testobj = S_new_testobj();
+    CharBuf *string = Obj_To_String(testobj);
+    Obj *dump = Obj_Dump(testobj);
+    TEST_TRUE(batch, Obj_Equals(dump, (Obj*)string),
+              "Default Dump returns To_String");
+    DECREF(dump);
+    DECREF(string);
+    DECREF(testobj);
+}
+
+static void
+test_Equals(TestBatch *batch) {
+    Obj *testobj = S_new_testobj();
+    Obj *other   = S_new_testobj();
+
+    TEST_TRUE(batch, Obj_Equals(testobj, testobj),
+              "Equals is true for the same object");
+    TEST_FALSE(batch, Obj_Equals(testobj, other),
+               "Distinct objects are not equal");
+
+    DECREF(testobj);
+    DECREF(other);
+}
+
+static void
+test_Hash_Sum(TestBatch *batch) {
+    Obj *testobj = S_new_testobj();
+    int64_t address64 = PTR_TO_I64(testobj);
+    int32_t address32 = (int32_t)address64;
+    TEST_TRUE(batch, (Obj_Hash_Sum(testobj) == address32),
+              "Hash_Sum uses memory address");
+    DECREF(testobj);
+}
+
+static void
+test_Is_A(TestBatch *batch) {
+    CharBuf *charbuf   = CB_new(0);
+    VTable  *bb_vtable = CB_Get_VTable(charbuf);
+    CharBuf *klass     = CB_Get_Class_Name(charbuf);
+
+    TEST_TRUE(batch, CB_Is_A(charbuf, CHARBUF), "CharBuf Is_A CharBuf.");
+    TEST_TRUE(batch, CB_Is_A(charbuf, OBJ), "CharBuf Is_A Obj.");
+    TEST_TRUE(batch, bb_vtable == CHARBUF, "Get_VTable");
+    TEST_TRUE(batch, CB_Equals(VTable_Get_Name(CHARBUF), (Obj*)klass),
+              "Get_Class_Name");
+
+    DECREF(charbuf);
+}
+
+static void
+S_attempt_init(void *context) {
+    Obj_init((Obj*)context);
+}
+
+static void
+S_attempt_Clone(void *context) {
+    Obj_Clone((Obj*)context);
+}
+
+static void
+S_attempt_Make(void *context) {
+    Obj_Make((Obj*)context);
+}
+
+static void
+S_attempt_Compare_To(void *context) {
+    Obj_Compare_To((Obj*)context, (Obj*)context);
+}
+
+static void
+S_attempt_To_I64(void *context) {
+    Obj_To_I64((Obj*)context);
+}
+
+static void
+S_attempt_To_F64(void *context) {
+    Obj_To_F64((Obj*)context);
+}
+
+static void
+S_attempt_Load(void *context) {
+    Obj_Load((Obj*)context, (Obj*)context);
+}
+
+static void
+S_attempt_Mimic(void *context) {
+    Obj_Mimic((Obj*)context, (Obj*)context);
+}
+
+static void
+S_verify_abstract_error(TestBatch *batch, Err_Attempt_t routine,
+                        void *context, const char *name) {
+    char message[100];
+    sprintf(message, "%s() is abstract", name);
+    Err *error = Err_trap(routine, context);
+    TEST_TRUE(batch, error != NULL
+              && Err_Is_A(error, ERR) 
+              && CB_Find_Str(Err_Get_Mess(error), "bstract", 7) != -1,
+              message);
+    DECREF(error);
+}
+
+static void
+test_abstract_routines(TestBatch *batch) {
+    Obj *blank = VTable_Make_Obj(OBJ);
+    S_verify_abstract_error(batch, S_attempt_init, blank, "init");
+
+    Obj *obj = S_new_testobj();
+    S_verify_abstract_error(batch, S_attempt_Clone,      obj, "Clone");
+    S_verify_abstract_error(batch, S_attempt_Make,       obj, "Make");
+    S_verify_abstract_error(batch, S_attempt_Compare_To, obj, "Compare_To");
+    S_verify_abstract_error(batch, S_attempt_To_I64,     obj, "To_I64");
+    S_verify_abstract_error(batch, S_attempt_To_F64,     obj, "To_F64");
+    S_verify_abstract_error(batch, S_attempt_Load,       obj, "Load");
+    S_verify_abstract_error(batch, S_attempt_Mimic,      obj, "Mimic");
+    DECREF(obj);
+}
+
+void
+TestObj_run_tests(TestObj *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_refcounts(batch);
+    test_To_String(batch);
+    test_Dump(batch);
+    test_Equals(batch);
+    test_Hash_Sum(batch);
+    test_Is_A(batch);
+    test_abstract_routines(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestObj.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestObj.cfh b/core/Clownfish/Test/TestObj.cfh
new file mode 100644
index 0000000..3c41f2b
--- /dev/null
+++ b/core/Clownfish/Test/TestObj.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::TestObj
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestObj*
+    new(TestFormatter *formatter);
+
+    inert TestObj*
+    init(TestObj *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestObj *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestUtils.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestUtils.c b/core/Clownfish/Test/TestUtils.c
new file mode 100644
index 0000000..0f7b72a
--- /dev/null
+++ b/core/Clownfish/Test/TestUtils.c
@@ -0,0 +1,140 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
+#define LUCY_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestUtils.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Util/Memory.h"
+#include "Lucy/Store/InStream.h"
+#include "Lucy/Store/OutStream.h"
+#include "Lucy/Store/RAMFile.h"
+#include "Lucy/Util/Freezer.h"
+
+uint64_t
+TestUtils_random_u64() {
+    uint64_t num = ((uint64_t)(rand()   & 0x7FFF) << 60)
+                   | ((uint64_t)(rand() & 0x7FFF) << 45)
+                   | ((uint64_t)(rand() & 0x7FFF) << 30)
+                   | ((uint64_t)(rand() & 0x7FFF) << 15)
+                   | ((uint64_t)(rand() & 0x7FFF) << 0);
+    return num;
+}
+
+int64_t*
+TestUtils_random_i64s(int64_t *buf, size_t count, int64_t min,
+                      int64_t limit) {
+    uint64_t  range = min < limit ? limit - min : 0;
+    int64_t *ints = buf ? buf : (int64_t*)CALLOCATE(count, sizeof(int64_t));
+    for (size_t i = 0; i < count; i++) {
+        ints[i] = min + TestUtils_random_u64() % range;
+    }
+    return ints;
+}
+
+uint64_t*
+TestUtils_random_u64s(uint64_t *buf, size_t count, uint64_t min,
+                      uint64_t limit) {
+    uint64_t  range = min < limit ? limit - min : 0;
+    uint64_t *ints = buf ? buf : (uint64_t*)CALLOCATE(count, sizeof(uint64_t));
+    for (size_t i = 0; i < count; i++) {
+        ints[i] = min + TestUtils_random_u64() % range;
+    }
+    return ints;
+}
+
+double*
+TestUtils_random_f64s(double *buf, size_t count) {
+    double *f64s = buf ? buf : (double*)CALLOCATE(count, sizeof(double));
+    for (size_t i = 0; i < count; i++) {
+        uint64_t num = TestUtils_random_u64();
+        f64s[i] = U64_TO_DOUBLE(num) / UINT64_MAX;
+    }
+    return f64s;
+}
+
+static uint32_t
+S_random_code_point(void) {
+    uint32_t code_point = 0;
+    while (1) {
+        uint8_t chance = (rand() % 9) + 1;
+        switch (chance) {
+            case 1: case 2: case 3:
+                code_point = rand() % 0x80;
+                break;
+            case 4: case 5: case 6:
+                code_point = (rand() % (0x0800  - 0x0080)) + 0x0080;
+                break;
+            case 7: case 8:
+                code_point = (rand() % (0x10000 - 0x0800)) + 0x0800;
+                break;
+            case 9: {
+                    uint64_t num = TestUtils_random_u64();
+                    code_point = (num % (0x10FFFF - 0x10000)) + 0x10000;
+                }
+        }
+        if (code_point > 0x10FFFF) {
+            continue; // Too high.
+        }
+        if (code_point > 0xD7FF && code_point < 0xE000) {
+            continue; // UTF-16 surrogate.
+        }
+        break;
+    }
+    return code_point;
+}
+
+CharBuf*
+TestUtils_random_string(size_t length) {
+    CharBuf *string = CB_new(length);
+    while (length--) {
+        CB_Cat_Char(string, S_random_code_point());
+    }
+    return string;
+}
+
+CharBuf*
+TestUtils_get_cb(const char *ptr) {
+    return CB_new_from_utf8(ptr, strlen(ptr));
+}
+
+Obj*
+TestUtils_freeze_thaw(Obj *object) {
+    if (object) {
+        RAMFile *ram_file = RAMFile_new(NULL, false);
+        OutStream *outstream = OutStream_open((Obj*)ram_file);
+        FREEZE(object, outstream);
+        OutStream_Close(outstream);
+        DECREF(outstream);
+
+        InStream *instream = InStream_open((Obj*)ram_file);
+        Obj *retval = THAW(instream);
+        DECREF(instream);
+        DECREF(ram_file);
+        return retval;
+    }
+    else {
+        return NULL;
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestUtils.cfh b/core/Clownfish/Test/TestUtils.cfh
new file mode 100644
index 0000000..5c88ec4
--- /dev/null
+++ b/core/Clownfish/Test/TestUtils.cfh
@@ -0,0 +1,71 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Clownfish;
+
+inert class Clownfish::Test::TestUtils  {
+
+    /** Testing-only CharBuf factory which uses strlen().
+     */
+    inert incremented CharBuf*
+    get_cb(const char *utf8);
+
+    /** Return a random unsigned 64-bit integer.
+     */
+    inert uint64_t
+    random_u64();
+
+    /** Return an array of <code>count</code> random 64-bit integers where
+     * <code>min <= n < limit</code>.
+     *
+     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
+     * be used.
+     */
+    inert int64_t*
+    random_i64s(int64_t *buf, size_t count, int64_t min, int64_t limit);
+
+    /** Return an array of <code>count</code> random unsigned, 64-bit integers
+     * where <code>min <= n < limit</code>.
+     *
+     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
+     * be used.
+     */
+    inert uint64_t*
+    random_u64s(uint64_t *buf, size_t count, uint64_t min, uint64_t limit);
+
+    /** Return an array of <code>count</code> random double-precision floating
+     * point numbers between 0 and 1.
+     *
+     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
+     * be used.
+     */
+    inert double*
+    random_f64s(double *buf, size_t count);
+
+    /** Return a string with a random (legal) sequence of code points.
+     * @param length Length of the string in code points.
+     */
+    inert incremented CharBuf*
+    random_string(size_t length);
+
+    /** Return the result of round-tripping the object through FREEZE and
+     * THAW.
+     */
+    inert incremented Obj*
+    freeze_thaw(Obj *object);
+}
+
+


[lucy-commits] [14/26] Move test harness classes to Clownfish::TestHarness

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Util/TestMemoryPool.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestMemoryPool.c b/core/Lucy/Test/Util/TestMemoryPool.c
index b7a63ae..69b5620 100644
--- a/core/Lucy/Test/Util/TestMemoryPool.c
+++ b/core/Lucy/Test/Util/TestMemoryPool.c
@@ -19,7 +19,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Util/TestMemoryPool.h"
 #include "Lucy/Util/MemoryPool.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Util/TestMemoryPool.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestMemoryPool.cfh b/core/Lucy/Test/Util/TestMemoryPool.cfh
index a0762e3..378567a 100644
--- a/core/Lucy/Test/Util/TestMemoryPool.cfh
+++ b/core/Lucy/Test/Util/TestMemoryPool.cfh
@@ -17,7 +17,7 @@
 parcel TestLucy;
 
 class Lucy::Test::Util::TestMemoryPool cnick TestMemPool
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestMemoryPool*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Util/TestPriorityQueue.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestPriorityQueue.c b/core/Lucy/Test/Util/TestPriorityQueue.c
index 420f301..56dc58c 100644
--- a/core/Lucy/Test/Util/TestPriorityQueue.c
+++ b/core/Lucy/Test/Util/TestPriorityQueue.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Util/TestPriorityQueue.h"
 #include "Lucy/Util/PriorityQueue.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Lucy/Test/Util/TestPriorityQueue.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestPriorityQueue.cfh b/core/Lucy/Test/Util/TestPriorityQueue.cfh
index 19f56f5..02f591d 100644
--- a/core/Lucy/Test/Util/TestPriorityQueue.cfh
+++ b/core/Lucy/Test/Util/TestPriorityQueue.cfh
@@ -27,7 +27,7 @@ class Lucy::Test::Util::NumPriorityQueue cnick NumPriQ
 }
 
 class Lucy::Test::Util::TestPriorityQueue cnick TestPriQ
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPriorityQueue*
     new(TestFormatter *formatter);


[lucy-commits] [13/26] git commit: refs/heads/separate-clownfish-wip2 - Move Clownfish classes to parcel Clownfish

Posted by nw...@apache.org.
Move Clownfish classes to parcel Clownfish


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/05fa0688
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/05fa0688
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/05fa0688

Branch: refs/heads/separate-clownfish-wip2
Commit: 05fa06888213def35a7907d9816fa53d90b69e48
Parents: fa4918d
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 20 16:54:45 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:17 2013 +0200

----------------------------------------------------------------------
 c/src/Clownfish/Err.c                              |    1 +
 c/src/Clownfish/LockFreeRegistry.c                 |    3 +-
 c/src/Clownfish/Obj.c                              |    3 +-
 c/src/Clownfish/VTable.c                           |    5 +-
 c/src/Lucy/Analysis/RegexTokenizer.c               |    1 +
 c/src/Lucy/Document/Doc.c                          |    1 +
 c/src/Lucy/Index/DocReader.c                       |    1 +
 c/src/Lucy/Index/Inverter.c                        |    1 +
 clownfish/compiler/src/CFCBindAliases.c            |  229 ---------------
 clownfish/compiler/src/CFCBindClass.c              |    9 +-
 clownfish/compiler/src/CFCBindCore.c               |   20 +-
 clownfish/compiler/src/CFCDumpable.c               |   14 +-
 clownfish/compiler/src/CFCPerl.c                   |    3 +-
 clownfish/compiler/src/CFCPerlSub.c                |    4 +-
 clownfish/compiler/src/CFCPerlTypeMap.c            |   30 +--
 clownfish/runtime/core/Clownfish/ByteBuf.c         |    5 +-
 clownfish/runtime/core/Clownfish/CharBuf.c         |    7 +-
 clownfish/runtime/core/Clownfish/Err.c             |    7 +-
 clownfish/runtime/core/Clownfish/Hash.c            |    5 +-
 .../runtime/core/Clownfish/LockFreeRegistry.c      |    3 +-
 clownfish/runtime/core/Clownfish/Method.c          |    3 +-
 clownfish/runtime/core/Clownfish/Num.c             |   19 +-
 clownfish/runtime/core/Clownfish/Obj.c             |    5 +-
 clownfish/runtime/core/Clownfish/Test.c            |    3 +-
 .../runtime/core/Clownfish/Test/TestByteBuf.c      |    1 +
 .../runtime/core/Clownfish/Test/TestCharBuf.c      |    1 +
 clownfish/runtime/core/Clownfish/Test/TestErr.c    |    1 +
 clownfish/runtime/core/Clownfish/Test/TestHash.c   |    1 +
 .../core/Clownfish/Test/TestLockFreeRegistry.c     |    1 +
 clownfish/runtime/core/Clownfish/Test/TestNum.c    |    1 +
 clownfish/runtime/core/Clownfish/Test/TestObj.c    |    1 +
 clownfish/runtime/core/Clownfish/Test/TestUtils.c  |    1 +
 clownfish/runtime/core/Clownfish/Test/TestVArray.c |    1 +
 .../runtime/core/Clownfish/Test/Util/TestAtomic.c  |    1 +
 .../runtime/core/Clownfish/Test/Util/TestMemory.c  |    1 +
 .../core/Clownfish/Test/Util/TestNumberUtils.c     |    1 +
 .../core/Clownfish/Test/Util/TestStringHelper.c    |    1 +
 clownfish/runtime/core/Clownfish/Util/Atomic.c     |    3 +-
 clownfish/runtime/core/Clownfish/Util/Memory.c     |    3 +-
 .../runtime/core/Clownfish/Util/NumberUtils.c      |    3 +-
 clownfish/runtime/core/Clownfish/Util/SortUtils.c  |    3 +-
 .../runtime/core/Clownfish/Util/StringHelper.c     |    3 +-
 clownfish/runtime/core/Clownfish/VArray.c          |    3 +-
 clownfish/runtime/core/Clownfish/VTable.c          |    9 +-
 clownfish/runtime/perl/xs/XSBind.c                 |    6 +-
 core/Clownfish.cfp                                 |    5 +
 core/Clownfish/ByteBuf.c                           |    5 +-
 core/Clownfish/ByteBuf.cfh                         |    2 +-
 core/Clownfish/CharBuf.c                           |    7 +-
 core/Clownfish/CharBuf.cfh                         |    4 +-
 core/Clownfish/Err.c                               |    7 +-
 core/Clownfish/Err.cfh                             |    6 +-
 core/Clownfish/Hash.c                              |    5 +-
 core/Clownfish/Hash.cfh                            |    2 +-
 core/Clownfish/LockFreeRegistry.c                  |    3 +-
 core/Clownfish/LockFreeRegistry.cfh                |    2 +-
 core/Clownfish/Method.c                            |    3 +-
 core/Clownfish/Method.cfh                          |    2 +-
 core/Clownfish/Num.c                               |   19 +-
 core/Clownfish/Num.cfh                             |    2 +-
 core/Clownfish/Obj.c                               |    5 +-
 core/Clownfish/Obj.cfh                             |    4 +-
 core/Clownfish/Test/TestBatch.c                    |    3 +-
 core/Clownfish/Test/TestBatch.cfh                  |    2 +-
 core/Clownfish/Test/TestFormatter.c                |    3 +-
 core/Clownfish/Test/TestFormatter.cfh              |    2 +-
 core/Clownfish/Test/TestRunner.c                   |    3 +-
 core/Clownfish/Test/TestRunner.cfh                 |    2 +-
 core/Clownfish/Util/Atomic.c                       |    3 +-
 core/Clownfish/Util/Atomic.cfh                     |    4 +-
 core/Clownfish/Util/Memory.c                       |    3 +-
 core/Clownfish/Util/Memory.cfh                     |    4 +-
 core/Clownfish/Util/NumberUtils.c                  |    3 +-
 core/Clownfish/Util/NumberUtils.cfh                |    4 +-
 core/Clownfish/Util/SortUtils.c                    |    3 +-
 core/Clownfish/Util/SortUtils.cfh                  |    2 +-
 core/Clownfish/Util/StringHelper.c                 |    3 +-
 core/Clownfish/Util/StringHelper.cfh               |    4 +-
 core/Clownfish/VArray.c                            |    3 +-
 core/Clownfish/VArray.cfh                          |    4 +-
 core/Clownfish/VTable.c                            |    9 +-
 core/Clownfish/VTable.cfh                          |    2 +-
 core/Lucy.c                                        |    6 +-
 core/Lucy/Search/Matcher.c                         |    1 +
 core/Lucy/Search/QueryParser.c                     |    2 +-
 core/Lucy/Util/Debug.c                             |    1 +
 core/Lucy/Util/ToolSet.h                           |    1 +
 example-lang/src/Lucy/Object/LockFreeRegistry.c    |    2 +-
 example-lang/src/Lucy/Object/Obj.c                 |    2 +-
 example-lang/src/Lucy/Object/VTable.c              |    4 +-
 perl/buildlib/Lucy/Build/Binding/Object.pm         |   20 +-
 perl/buildlib/Lucy/Build/Binding/Util.pm           |    2 +-
 perl/xs/XSBind.c                                   |    6 +-
 ruby/src/Lucy/Object/LockFreeRegistry.c            |    2 +-
 ruby/src/Lucy/Object/Obj.c                         |    2 +-
 ruby/src/Lucy/Object/VTable.c                      |    4 +-
 96 files changed, 222 insertions(+), 410 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/c/src/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/c/src/Clownfish/Err.c b/c/src/Clownfish/Err.c
index 2adb533..a932ee2 100644
--- a/c/src/Clownfish/Err.c
+++ b/c/src/Clownfish/Err.c
@@ -15,6 +15,7 @@
  */
 
 #define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 
 #include <setjmp.h>

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/c/src/Clownfish/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/c/src/Clownfish/LockFreeRegistry.c b/c/src/Clownfish/LockFreeRegistry.c
index 92c121c..83683c3 100644
--- a/c/src/Clownfish/LockFreeRegistry.c
+++ b/c/src/Clownfish/LockFreeRegistry.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_LOCKFREEREGISTRY
+#define C_CFISH_LOCKFREEREGISTRY
 #define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 
 #include "Clownfish/LockFreeRegistry.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/c/src/Clownfish/Obj.c
----------------------------------------------------------------------
diff --git a/c/src/Clownfish/Obj.c b/c/src/Clownfish/Obj.c
index cf344b1..b27f632 100644
--- a/c/src/Clownfish/Obj.c
+++ b/c/src/Clownfish/Obj.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_OBJ
+#define C_CFISH_OBJ
 #define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 
 #include "Clownfish/Obj.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/c/src/Clownfish/VTable.c
----------------------------------------------------------------------
diff --git a/c/src/Clownfish/VTable.c b/c/src/Clownfish/VTable.c
index 09fce4e..22dc34e 100644
--- a/c/src/Clownfish/VTable.c
+++ b/c/src/Clownfish/VTable.c
@@ -15,9 +15,10 @@
  */
 
 #define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
+#define C_CFISH_OBJ
+#define C_CFISH_VTABLE
 
 #include "Clownfish/VTable.h"
 #include "Clownfish/CharBuf.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/c/src/Lucy/Analysis/RegexTokenizer.c
----------------------------------------------------------------------
diff --git a/c/src/Lucy/Analysis/RegexTokenizer.c b/c/src/Lucy/Analysis/RegexTokenizer.c
index d2d3bbb..e2e5277 100644
--- a/c/src/Lucy/Analysis/RegexTokenizer.c
+++ b/c/src/Lucy/Analysis/RegexTokenizer.c
@@ -16,6 +16,7 @@
 
 #define C_LUCY_REGEXTOKENIZER
 #define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 
 #include "charmony.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/c/src/Lucy/Document/Doc.c
----------------------------------------------------------------------
diff --git a/c/src/Lucy/Document/Doc.c b/c/src/Lucy/Document/Doc.c
index 8b44af2..92d33f3 100644
--- a/c/src/Lucy/Document/Doc.c
+++ b/c/src/Lucy/Document/Doc.c
@@ -16,6 +16,7 @@
 
 #define C_LUCY_DOC
 #define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 
 #include "Lucy/Document/Doc.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/c/src/Lucy/Index/DocReader.c
----------------------------------------------------------------------
diff --git a/c/src/Lucy/Index/DocReader.c b/c/src/Lucy/Index/DocReader.c
index e06e7ee..79fcd4f 100644
--- a/c/src/Lucy/Index/DocReader.c
+++ b/c/src/Lucy/Index/DocReader.c
@@ -17,6 +17,7 @@
 #define C_LUCY_DOCREADER
 #define C_LUCY_DEFAULTDOCREADER
 #define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 
 #include "Lucy/Index/DocReader.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/c/src/Lucy/Index/Inverter.c
----------------------------------------------------------------------
diff --git a/c/src/Lucy/Index/Inverter.c b/c/src/Lucy/Index/Inverter.c
index cfaafcd..0700075 100644
--- a/c/src/Lucy/Index/Inverter.c
+++ b/c/src/Lucy/Index/Inverter.c
@@ -17,6 +17,7 @@
 #define C_LUCY_INVERTER
 #define C_LUCY_INVERTERENTRY
 #define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 
 #include "Lucy/Index/Inverter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/compiler/src/CFCBindAliases.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCBindAliases.c b/clownfish/compiler/src/CFCBindAliases.c
index c32f925..12890ad 100644
--- a/clownfish/compiler/src/CFCBindAliases.c
+++ b/clownfish/compiler/src/CFCBindAliases.c
@@ -25,235 +25,6 @@ struct alias {
 
 struct alias aliases[] = {
     {"CFISH_VISIBLE", "LUCY_VISIBLE"},
-
-    {"cfish_Obj", "lucy_Obj"},
-    {"CFISH_OBJ", "LUCY_OBJ"},
-    {"cfish_Obj_dec_refcount", "lucy_Obj_dec_refcount"},
-    {"cfish_Obj_get_refcount", "lucy_Obj_get_refcount"},
-    {"cfish_Obj_inc_refcount", "lucy_Obj_inc_refcount"},
-    {"cfish_Obj_to_host", "lucy_Obj_to_host"},
-    {"Cfish_Obj_Dec_RefCount", "Lucy_Obj_Dec_RefCount"},
-    {"Cfish_Obj_Deserialize", "Lucy_Obj_Deserialize"},
-    {"Cfish_Obj_Destroy", "Lucy_Obj_Destroy"},
-    {"Cfish_Obj_Destroy_OFFSET", "Lucy_Obj_Destroy_OFFSET"},
-    {"Cfish_Obj_Destroy_t", "Lucy_Obj_Destroy_t"},
-    {"Cfish_Obj_Dump", "Lucy_Obj_Dump"},
-    {"Cfish_Obj_Get_Class_Name", "Lucy_Obj_Get_Class_Name"},
-    {"Cfish_Obj_Inc_RefCount", "Lucy_Obj_Inc_RefCount"},
-    {"Cfish_Obj_Is_A", "Lucy_Obj_Is_A"},
-    {"Cfish_Obj_Load", "Lucy_Obj_Load"},
-    {"Cfish_Obj_Load_OFFSET", "Lucy_Obj_Load_OFFSET"},
-    {"Cfish_Obj_Load_t", "Lucy_Obj_Load_t"},
-    {"Cfish_Obj_Serialize", "Lucy_Obj_Serialize"},
-    {"Cfish_Obj_To_F64", "Lucy_Obj_To_F64"},
-    {"Cfish_Obj_To_I64", "Lucy_Obj_To_I64"},
-    {"Cfish_Obj_To_Bool", "Lucy_Obj_To_Bool"},
-    {"Cfish_Obj_To_Host", "Lucy_Obj_To_Host"},
-
-    {"cfish_ByteBuf", "lucy_ByteBuf"},
-    {"CFISH_BYTEBUF", "LUCY_BYTEBUF"},
-    {"cfish_BB_init", "lucy_BB_init"},
-    {"Cfish_BB_Deserialize", "Lucy_BB_Deserialize"},
-    {"Cfish_BB_Get_Buf", "Lucy_BB_Get_Buf"},
-    {"Cfish_BB_Get_Size", "Lucy_BB_Get_Size"},
-    {"Cfish_BB_Mimic_Bytes", "Lucy_BB_Mimic_Bytes"},
-    {"Cfish_BB_To_Host", "Lucy_BB_To_Host"},
-    {"cfish_ViewByteBuf", "lucy_ViewByteBuf"},
-    {"cfish_ViewBB_new", "lucy_ViewBB_new"},
-    {"Cfish_ViewBB_Assign_Bytes", "Lucy_ViewBB_Assign_Bytes"},
-
-    {"cfish_CharBuf", "lucy_CharBuf"},
-    {"CFISH_CHARBUF", "LUCY_CHARBUF"},
-    {"cfish_CB_clone", "lucy_CB_clone"},
-    {"cfish_CB_newf", "lucy_CB_newf"},
-    {"cfish_CB_new_from_trusted_utf8", "lucy_CB_new_from_trusted_utf8"},
-    {"cfish_CB_init", "lucy_CB_init"},
-    {"Cfish_CB_Cat_Trusted_Str", "Lucy_CB_Cat_Trusted_Str"},
-    {"Cfish_CB_Clone", "Lucy_CB_Clone"},
-    {"Cfish_CB_Deserialize", "Lucy_CB_Deserialize"},
-    {"Cfish_CB_Find_Str", "Lucy_CB_Find_Str"},
-    {"Cfish_CB_Get_Ptr8", "Lucy_CB_Get_Ptr8"},
-    {"Cfish_CB_Get_Size", "Lucy_CB_Get_Size"},
-    {"Cfish_CB_Mimic_Str", "Lucy_CB_Mimic_Str"},
-    {"Cfish_CB_Nip_One_OFFSET", "Lucy_CB_Nip_One_OFFSET"},
-    {"Cfish_CB_Nip_One_t", "Lucy_CB_Nip_One_t"},
-    {"Cfish_CB_To_Host", "Lucy_CB_To_Host"},
-    {"cfish_ViewCharBuf", "lucy_ViewCharBuf"},
-    {"CFISH_VIEWCHARBUF", "LUCY_VIEWCHARBUF"},
-    {"cfish_ViewCB_new_from_trusted_utf8", "lucy_ViewCB_new_from_trusted_utf8"},
-    {"Cfish_ViewCB_Assign_Str", "Lucy_ViewCB_Assign_Str"},
-    {"cfish_ZombieCharBuf", "lucy_ZombieCharBuf"},
-    {"CFISH_ZOMBIECHARBUF", "LUCY_ZOMBIECHARBUF"},
-    {"cfish_ZCB_new", "lucy_ZCB_new"},
-    {"cfish_ZCB_size", "lucy_ZCB_size"},
-    {"cfish_ZCB_wrap", "lucy_ZCB_wrap"},
-    {"cfish_ZCB_wrap_str", "lucy_ZCB_wrap_str"},
-    {"Cfish_ZCB_Assign_Str", "Lucy_ZCB_Assign_Str"},
-    {"Cfish_ZCB_Assign_Trusted_Str", "Lucy_ZCB_Assign_Trusted_Str"},
-
-    {"CFISH_FLOATNUM", "LUCY_FLOATNUM"},
-    {"CFISH_INTNUM", "LUCY_INTNUM"},
-    {"CFISH_INTEGER32", "LUCY_INTEGER32"},
-    {"CFISH_INTEGER64", "LUCY_INTEGER64"},
-    {"CFISH_FLOAT32", "LUCY_FLOAT32"},
-    {"CFISH_FLOAT64", "LUCY_FLOAT64"},
-    {"cfish_Bool_false_singleton", "lucy_Bool_false_singleton"},
-    {"cfish_Bool_true_singleton", "lucy_Bool_true_singleton"},
-    {"cfish_Bool_singleton", "lucy_Bool_singleton"},
-    {"Cfish_Bool_Dec_RefCount_OFFSET", "Lucy_Bool_Dec_RefCount_OFFSET"},
-    {"Cfish_Bool_Dec_RefCount_t", "Lucy_Bool_Dec_RefCount_t"},
-
-    {"cfish_Err", "lucy_Err"},
-    {"CFISH_ERR", "LUCY_ERR"},
-    {"cfish_Err_certify", "lucy_Err_certify"},
-    {"cfish_Err_do_throw", "lucy_Err_do_throw"},
-    {"cfish_Err_downcast", "lucy_Err_downcast"},
-    {"cfish_Err_get_error", "lucy_Err_get_error"},
-    {"cfish_Err_init_class", "lucy_Err_init_class"},
-    {"cfish_Err_make_mess", "lucy_Err_make_mess"},
-    {"cfish_Err_new", "lucy_Err_new"},
-    {"cfish_Err_rethrow", "lucy_Err_rethrow"},
-    {"cfish_Err_set_error", "lucy_Err_set_error"},
-    {"cfish_Err_throw_at", "lucy_Err_throw_at"},
-    {"cfish_Err_throw_mess", "lucy_Err_throw_mess"},
-    {"cfish_Err_to_host", "lucy_Err_to_host"},
-    {"cfish_Err_trap", "lucy_Err_trap"},
-    {"cfish_Err_warn_at", "lucy_Err_warn_at"},
-    {"cfish_Err_warn_mess", "lucy_Err_warn_mess"},
-    {"Cfish_Err_Add_Frame", "Lucy_Err_Add_Frame"},
-    {"Cfish_Err_Cat_Mess", "Lucy_Err_Cat_Mess"},
-    {"Cfish_Err_Make_OFFSET", "Lucy_Err_Make_OFFSET"},
-    {"Cfish_Err_Make_t", "Lucy_Err_Make_t"},
-    {"Cfish_Err_To_Host", "Lucy_Err_To_Host"},
-    {"Cfish_Err_To_Host_OFFSET", "Lucy_Err_To_Host_OFFSET"},
-    {"Cfish_Err_To_Host_t", "Lucy_Err_To_Host_t"},
-
-    {"cfish_Hash", "lucy_Hash"},
-    {"CFISH_HASH", "LUCY_HASH"},
-    {"cfish_Hash_new", "lucy_Hash_new"},
-    {"cfish_Hash_fetch", "lucy_Hash_fetch"},
-    {"cfish_Hash_store", "lucy_Hash_store"},
-    {"Cfish_Hash_Deserialize", "Lucy_Hash_Deserialize"},
-    {"Cfish_Hash_Fetch_Str", "Lucy_Hash_Fetch_Str"},
-    {"Cfish_Hash_Iterate", "Lucy_Hash_Iterate"},
-    {"Cfish_Hash_Next", "Lucy_Hash_Next"},
-    {"Cfish_Hash_Store_Str", "Lucy_Hash_Store_Str"},
-    {"Cfish_Hash_Store", "Lucy_Hash_Store"},
-    {"Cfish_Hash_To_Host", "Lucy_Hash_To_Host"},
-
-    {"cfish_LockFreeRegistry", "lucy_LockFreeRegistry"},
-    {"CFISH_LOCKFREEREGISTRY", "LUCY_LOCKFREEREGISTRY"},
-    {"cfish_LFReg_to_host", "lucy_LFReg_to_host"},
-    {"Cfish_LFReg_To_Host", "Lucy_LFReg_To_Host"},
-    {"Cfish_LFReg_To_Host_OFFSET", "Lucy_LFReg_To_Host_OFFSET"},
-    {"Cfish_LFReg_To_Host_t", "Lucy_LFReg_To_Host_t"},
-
-    {"cfish_Memory_wrapped_calloc", "lucy_Memory_wrapped_calloc"},
-    {"cfish_Memory_wrapped_free", "lucy_Memory_wrapped_free"},
-    {"cfish_Memory_wrapped_malloc", "lucy_Memory_wrapped_malloc"},
-    {"cfish_Memory_wrapped_realloc", "lucy_Memory_wrapped_realloc"},
-
-    {"cfish_Float32", "lucy_Float32"},
-    {"cfish_Float32_init", "lucy_Float32_init"},
-    {"Cfish_Float32_Set_Value", "Lucy_Float32_Set_Value"},
-    {"cfish_Float64", "lucy_Float64"},
-    {"cfish_Float64_init", "lucy_Float64_init"},
-    {"Cfish_Float64_Set_Value", "Lucy_Float64_Set_Value"},
-    {"cfish_Integer32", "lucy_Integer32"},
-    {"Cfish_Int32_Set_Value", "Lucy_Int32_Set_Value"},
-    {"cfish_Integer64", "lucy_Integer64"},
-    {"Cfish_Int64_Set_Value", "Lucy_Int64_Set_Value"},
-
-    {"cfish_NumUtil_decode_bigend_f32", "lucy_NumUtil_decode_bigend_f32"},
-    {"cfish_NumUtil_decode_bigend_f64", "lucy_NumUtil_decode_bigend_f64"},
-    {"cfish_NumUtil_decode_bigend_u16", "lucy_NumUtil_decode_bigend_u16"},
-    {"cfish_NumUtil_decode_bigend_u32", "lucy_NumUtil_decode_bigend_u32"},
-    {"cfish_NumUtil_decode_bigend_u64", "lucy_NumUtil_decode_bigend_u64"},
-    {"cfish_NumUtil_decode_c32", "lucy_NumUtil_decode_c32"},
-    {"cfish_NumUtil_decode_c64", "lucy_NumUtil_decode_c64"},
-    {"cfish_NumUtil_encode_bigend_f32", "lucy_NumUtil_encode_bigend_f32"},
-    {"cfish_NumUtil_encode_bigend_f64", "lucy_NumUtil_encode_bigend_f64"},
-    {"cfish_NumUtil_encode_bigend_u16", "lucy_NumUtil_encode_bigend_u16"},
-    {"cfish_NumUtil_encode_bigend_u32", "lucy_NumUtil_encode_bigend_u32"},
-    {"cfish_NumUtil_encode_bigend_u64", "lucy_NumUtil_encode_bigend_u64"},
-    {"cfish_NumUtil_encode_c32", "lucy_NumUtil_encode_c32"},
-    {"cfish_NumUtil_encode_c64", "lucy_NumUtil_encode_c64"},
-    {"cfish_NumUtil_encode_padded_c32", "lucy_NumUtil_encode_padded_c32"},
-    {"cfish_NumUtil_u1clear", "lucy_NumUtil_u1clear"},
-    {"cfish_NumUtil_u1flip", "lucy_NumUtil_u1flip"},
-    {"cfish_NumUtil_u1get", "lucy_NumUtil_u1get"},
-    {"cfish_NumUtil_u1set", "lucy_NumUtil_u1set"},
-    {"cfish_NumUtil_u1masks", "lucy_NumUtil_u1masks"},
-    {"cfish_NumUtil_u2get", "lucy_NumUtil_u2get"},
-    {"cfish_NumUtil_u2set", "lucy_NumUtil_u2set"},
-    {"cfish_NumUtil_u2masks", "lucy_NumUtil_u2masks"},
-    {"cfish_NumUtil_u2shifts", "lucy_NumUtil_u2shifts"},
-    {"cfish_NumUtil_u4get", "lucy_NumUtil_u4get"},
-    {"cfish_NumUtil_u4set", "lucy_NumUtil_u4set"},
-    {"cfish_NumUtil_u4masks", "lucy_NumUtil_u4masks"},
-    {"cfish_NumUtil_u4shifts", "lucy_NumUtil_u4shifts"},
-    {"cfish_NumUtil_skip_cint", "lucy_NumUtil_skip_cint"},
-
-    {"cfish_StrHelp_to_base36", "lucy_StrHelp_to_base36"},
-    {"cfish_StrHelp_utf8_valid", "lucy_StrHelp_utf8_valid"},
-    {"cfish_StrHelp_UTF8_COUNT", "lucy_StrHelp_UTF8_COUNT"},
-
-    {"cfish_TestBatch_fail", "lucy_TestBatch_fail"},
-    {"cfish_TestBatch_pass", "lucy_TestBatch_pass"},
-    {"cfish_TestBatch_skip", "lucy_TestBatch_skip"},
-    {"cfish_TestBatch_test_false", "lucy_TestBatch_test_false"},
-    {"cfish_TestBatch_test_float_equals", "lucy_TestBatch_test_float_equals"},
-    {"cfish_TestBatch_test_int_equals", "lucy_TestBatch_test_int_equals"},
-    {"cfish_TestBatch_test_string_equals", "lucy_TestBatch_test_string_equals"},
-    {"cfish_TestBatch_test_true", "lucy_TestBatch_test_true"},
-    {"cfish_TestFormatter", "lucy_TestFormatter"},
-    {"cfish_TestFormatterCF", "lucy_TestFormatterCF"},
-    {"cfish_TestFormatterCF_new", "lucy_TestFormatterCF_new"},
-    {"cfish_TestFormatterTAP", "lucy_TestFormatterTAP"},
-    {"cfish_TestFormatterTAP_new", "lucy_TestFormatterTAP_new"},
-
-    {"cfish_VArray", "lucy_VArray"},
-    {"CFISH_VARRAY", "LUCY_VARRAY"},
-    {"cfish_VA_new", "lucy_VA_new"},
-    {"cfish_VA_store", "lucy_VA_store"},
-    {"Cfish_VA_Clone", "Lucy_VA_Clone"},
-    {"Cfish_VA_Delete", "Lucy_VA_Delete"},
-    {"Cfish_VA_Deserialize", "Lucy_VA_Deserialize"},
-    {"Cfish_VA_Fetch", "Lucy_VA_Fetch"},
-    {"Cfish_VA_Get_Size", "Lucy_VA_Get_Size"},
-    {"Cfish_VA_Pop", "Lucy_VA_Pop"},
-    {"Cfish_VA_Push", "Lucy_VA_Push"},
-    {"Cfish_VA_Resize", "Lucy_VA_Resize"},
-    {"Cfish_VA_Shallow_Copy", "Lucy_VA_Shallow_Copy"},
-    {"Cfish_VA_Shift", "Lucy_VA_Shift"},
-    {"Cfish_VA_Store", "Lucy_VA_Store"},
-    {"Cfish_VA_To_Host", "Lucy_VA_To_Host"},
-
-    {"cfish_VTable", "lucy_VTable"},
-    {"CFISH_VTABLE", "LUCY_VTABLE"},
-    {"cfish_VTable_add_alias_to_registry", "lucy_VTable_add_alias_to_registry"},
-    {"cfish_VTable_bootstrap", "lucy_VTable_bootstrap"},
-    {"cfish_VTable_fetch_vtable", "lucy_VTable_fetch_vtable"},
-    {"cfish_VTable_find_parent_class", "lucy_VTable_find_parent_class"},
-    {"cfish_VTable_foster_obj", "lucy_VTable_foster_obj"},
-    {"cfish_VTable_fresh_host_methods", "lucy_VTable_fresh_host_methods"},
-    {"cfish_VTable_init_obj", "lucy_VTable_init_obj"},
-    {"cfish_VTable_init_registry", "lucy_VTable_init_registry"},
-    {"cfish_VTable_make_obj", "lucy_VTable_make_obj"},
-    {"cfish_VTable_offset_of_parent", "lucy_VTable_offset_of_parent"},
-    {"cfish_VTable_register_with_host", "lucy_VTable_register_with_host"},
-    {"cfish_VTable_registry", "lucy_VTable_registry"},
-    {"cfish_VTable_singleton", "lucy_VTable_singleton"},
-    {"cfish_VTable_to_host", "lucy_VTable_to_host"},
-    {"Cfish_VTable_Foster_Obj", "Lucy_VTable_Foster_Obj"},
-    {"Cfish_VTable_Get_Name", "Lucy_VTable_Get_Name"},
-    {"Cfish_VTable_Make_Obj", "Lucy_VTable_Make_Obj"},
-    {"Cfish_VTable_To_Host", "Lucy_VTable_To_Host"},
-    {"Cfish_VTable_To_Host_OFFSET", "Lucy_VTable_To_Host_OFFSET"},
-    {"Cfish_VTable_To_Host_t", "Lucy_VTable_To_Host_t"},
-
-    {"CFISH_USE_SHORT_NAMES", "LUCY_USE_SHORT_NAMES"},
-
     {NULL, NULL}
 };
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/compiler/src/CFCBindClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCBindClass.c b/clownfish/compiler/src/CFCBindClass.c
index 2cd5efd..9c4548a 100644
--- a/clownfish/compiler/src/CFCBindClass.c
+++ b/clownfish/compiler/src/CFCBindClass.c
@@ -119,7 +119,8 @@ CFCBindClass_to_c_header(CFCBindClass *self) {
 
 static char*
 S_to_c_header_inert(CFCBindClass *self) {
-    const char *prefix    = CFCClass_get_prefix(self->client);
+    //const char *prefix    = CFCClass_get_prefix(self->client);
+    const char *prefix    = "lucy_";
     char *inert_func_decs = S_sub_declarations(self);
     char *inert_var_defs  = S_inert_var_declarations(self);
     char *short_names     = S_short_names(self);
@@ -155,8 +156,10 @@ static char*
 S_to_c_header_dynamic(CFCBindClass *self) {
     const char *privacy_symbol  = CFCClass_privacy_symbol(self->client);
     const char *vt_var          = CFCClass_full_vtable_var(self->client);
-    const char *prefix          = CFCClass_get_prefix(self->client);
-    const char *PREFIX          = CFCClass_get_PREFIX(self->client);
+    //const char *prefix          = CFCClass_get_prefix(self->client);
+    //const char *PREFIX          = CFCClass_get_PREFIX(self->client);
+    const char *prefix          = "lucy_";
+    const char *PREFIX          = "LUCY_";
     char *struct_def            = S_struct_definition(self);
     char *parent_include        = S_parent_include(self);
     char *sub_declarations      = S_sub_declarations(self);

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/compiler/src/CFCBindCore.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCBindCore.c b/clownfish/compiler/src/CFCBindCore.c
index 63bcda3..ec36cab 100644
--- a/clownfish/compiler/src/CFCBindCore.c
+++ b/clownfish/compiler/src/CFCBindCore.c
@@ -146,7 +146,7 @@ S_write_parcel_h(CFCBindCore *self) {
         }
         if (!CFCClass_included(klass)) {
             if (parcel && CFCClass_get_parcel(klass) != parcel) {
-                CFCUtil_die("Multiple parcels not yet supported.");
+                //CFCUtil_die("Multiple parcels not yet supported.");
             }
             parcel = CFCClass_get_parcel(klass);
         }
@@ -156,8 +156,10 @@ S_write_parcel_h(CFCBindCore *self) {
     if (!parcel) {
         CFCUtil_die("No source classes found.");
     }
-    const char *prefix = CFCParcel_get_prefix(parcel);
-    const char *PREFIX = CFCParcel_get_PREFIX(parcel);
+    //const char *prefix = CFCParcel_get_prefix(parcel);
+    //const char *PREFIX = CFCParcel_get_PREFIX(parcel);
+    const char *prefix = "lucy_";
+    const char *PREFIX = "LUCY_";
 
     // Create Clownfish aliases if necessary.
     char *aliases = CFCBindAliases_c_aliases();
@@ -341,7 +343,7 @@ S_write_parcel_c(CFCBindCore *self) {
         privacy_syms = CFCUtil_cat(privacy_syms, "#define ",
                                    privacy_sym, "\n", NULL);
         if (parcel && CFCClass_get_parcel(klass) != parcel) {
-            CFCUtil_die("Multiple parcels not yet supported.");
+            //CFCUtil_die("Multiple parcels not yet supported.");
         }
         parcel = CFCClass_get_parcel(klass);
     }
@@ -351,12 +353,13 @@ S_write_parcel_c(CFCBindCore *self) {
     if (!parcel) {
         CFCUtil_die("No source classes found.");
     }
-    const char *prefix = CFCParcel_get_prefix(parcel);
+    //const char *prefix = CFCParcel_get_prefix(parcel);
+    const char *prefix = "lucy_";
 
     char pattern[] =
         "%s\n"
         "\n"
-        "#define C_LUCY_VTABLE\n"
+        "#define C_CFISH_VTABLE\n"
         "%s\n"
         "#include \"%sparcel.h\"\n"
         "#include \"callbacks.h\"\n"
@@ -425,7 +428,7 @@ CFCBindCore_write_callbacks_h(CFCBindCore *self) {
             CFCBase_decref((CFCBase*)class_binding);
 
             if (parcel && CFCClass_get_parcel(klass) != parcel) {
-                CFCUtil_die("Multiple parcels not yet supported.");
+                //CFCUtil_die("Multiple parcels not yet supported.");
             }
             parcel = CFCClass_get_parcel(klass);
         }
@@ -436,7 +439,8 @@ CFCBindCore_write_callbacks_h(CFCBindCore *self) {
     if (!parcel) {
         CFCUtil_die("No source classes found.");
     }
-    const char *prefix = CFCParcel_get_prefix(parcel);
+    //const char *prefix = CFCParcel_get_prefix(parcel);
+    const char *prefix = "lucy_";
 
     const char pattern[] =
         "%s\n"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/compiler/src/CFCDumpable.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCDumpable.c b/clownfish/compiler/src/CFCDumpable.c
index 006f62a..150b363 100644
--- a/clownfish/compiler/src/CFCDumpable.c
+++ b/clownfish/compiler/src/CFCDumpable.c
@@ -115,8 +115,8 @@ S_make_method_obj(CFCClass *klass, const char *method_name) {
     const char *klass_cnick  = CFCClass_get_cnick(klass);
     CFCParcel  *klass_parcel = CFCClass_get_parcel(klass);
 
-    CFCType *return_type
-        = CFCType_new_object(CFCTYPE_INCREMENTED, klass_parcel, "lucy_Obj", 1);
+    CFCType *return_type = CFCType_new_object(CFCTYPE_INCREMENTED,
+                                              klass_parcel, "cfish_Obj", 1);
     CFCType *self_type = CFCType_new_object(0, klass_parcel,
                                             klass_full_struct_sym, 1);
     CFCVariable *self_var = CFCVariable_new(NULL, NULL, NULL, NULL, "self",
@@ -128,7 +128,7 @@ S_make_method_obj(CFCClass *klass, const char *method_name) {
         CFCParamList_add_param(param_list, self_var, NULL);
     }
     else if (strcmp(method_name, "Load") == 0) {
-        CFCType *dump_type = CFCType_new_object(0, klass_parcel, "lucy_Obj",
+        CFCType *dump_type = CFCType_new_object(0, klass_parcel, "cfish_Obj",
                                                 1);
         CFCVariable *dump_var = CFCVariable_new(NULL, NULL, NULL, NULL, "dump",
                                                 dump_type, false);
@@ -178,7 +178,7 @@ S_add_dump_method(CFCClass *klass) {
             "cfish_Obj*\n"
             "%s(%s *self)\n"
             "{\n"
-            "    %s super_dump = SUPER_METHOD_PTR(%s, %s);\n"
+            "    %s super_dump = CFISH_SUPER_METHOD_PTR(%s, %s);\n"
             "    cfish_Hash *dump = (cfish_Hash*)super_dump(self);\n";
         char *autocode
             = CFCUtil_sprintf(pattern, full_func_sym, full_struct,
@@ -234,7 +234,7 @@ S_add_load_method(CFCClass *klass) {
             "%s(%s *self, cfish_Obj *dump)\n"
             "{\n"
             "    cfish_Hash *source = (cfish_Hash*)CFISH_CERTIFY(dump, CFISH_HASH);\n"
-            "    %s super_load = SUPER_METHOD_PTR(%s, %s);\n"
+            "    %s super_load = CFISH_SUPER_METHOD_PTR(%s, %s);\n"
             "    %s *loaded = (%s*)super_load(self, dump);\n";
         char *autocode
             = CFCUtil_sprintf(pattern, full_func_sym, full_struct,
@@ -286,7 +286,7 @@ S_process_dump_member(CFCClass *klass, CFCVariable *member, char *buf,
     const char *specifier = CFCType_get_specifier(type);
 
     // Skip the VTable.
-    if (strcmp(specifier, "lucy_VTable") == 0) {
+    if (strcmp(specifier, "cfish_VTable") == 0) {
         return;
     }
 
@@ -347,7 +347,7 @@ S_process_load_member(CFCClass *klass, CFCVariable *member, char *buf,
     const char *specifier = CFCType_get_specifier(type);
 
     // Skip the VTable.
-    if (strcmp(specifier, "lucy_VTable") == 0) {
+    if (strcmp(specifier, "cfish_VTable") == 0) {
         return;
     }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/compiler/src/CFCPerl.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCPerl.c b/clownfish/compiler/src/CFCPerl.c
index c7f971b..7263632 100644
--- a/clownfish/compiler/src/CFCPerl.c
+++ b/clownfish/compiler/src/CFCPerl.c
@@ -114,7 +114,8 @@ CFCPerl_init(CFCPerl *self, CFCParcel *parcel, CFCHierarchy *hierarchy,
     }
 
     // Derive the name of the "parcel.h" file.
-    self->parcel_h_file = CFCUtil_sprintf("%sparcel.h", prefix);
+    //self->parcel_h_file = CFCUtil_sprintf("%sparcel.h", prefix);
+    self->parcel_h_file = CFCUtil_sprintf("%sparcel.h", "lucy_");
 
     return self;
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/compiler/src/CFCPerlSub.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCPerlSub.c b/clownfish/compiler/src/CFCPerlSub.c
index af98cde..2b35ac5 100644
--- a/clownfish/compiler/src/CFCPerlSub.c
+++ b/clownfish/compiler/src/CFCPerlSub.c
@@ -147,9 +147,7 @@ S_allot_params_arg(CFCType *type, const char *label, int required) {
         // Share buffers rather than copy between Perl scalars and Clownfish
         // string types.
         int use_sv_buffer = false;
-        if (strcmp(struct_sym, "lucy_CharBuf") == 0
-            || strcmp(struct_sym, "cfish_CharBuf") == 0
-            || strcmp(struct_sym, "lucy_Obj") == 0
+        if (strcmp(struct_sym, "cfish_CharBuf") == 0
             || strcmp(struct_sym, "cfish_Obj") == 0
            ) {
             use_sv_buffer = true;

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/compiler/src/CFCPerlTypeMap.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCPerlTypeMap.c b/clownfish/compiler/src/CFCPerlTypeMap.c
index 22b0f15..08d12da 100644
--- a/clownfish/compiler/src/CFCPerlTypeMap.c
+++ b/clownfish/compiler/src/CFCPerlTypeMap.c
@@ -42,9 +42,7 @@ CFCPerlTypeMap_from_perl(CFCType *type, const char *xs_var) {
         const char *struct_sym = CFCType_get_specifier(type);
         const char *vtable_var = CFCType_get_vtable_var(type);
         const char *allocation;
-        if (strcmp(struct_sym, "lucy_CharBuf") == 0
-            || strcmp(struct_sym, "cfish_CharBuf") == 0
-            || strcmp(struct_sym, "lucy_Obj") == 0
+        if (strcmp(struct_sym, "cfish_CharBuf") == 0
             || strcmp(struct_sym, "cfish_Obj") == 0
            ) {
             // Share buffers rather than copy between Perl scalars and
@@ -275,32 +273,6 @@ CFCPerlTypeMap_write_xs_typemap(CFCHierarchy *hierarchy) {
         const char *full_struct_sym = CFCClass_full_struct_sym(klass);
         const char *vtable_var      = CFCClass_full_vtable_var(klass);
 
-        /* Temporary hack until the Clownfish parcel is ready. */
-        if (strcmp(full_struct_sym, "lucy_ByteBuf") == 0) {
-            full_struct_sym = "cfish_ByteBuf";
-            vtable_var      = "CFISH_BYTEBUF";
-        }
-        else if (strcmp(full_struct_sym, "lucy_CharBuf") == 0) {
-            full_struct_sym = "cfish_CharBuf";
-            vtable_var      = "CFISH_CHARBUF";
-        }
-        else if (strcmp(full_struct_sym, "lucy_Hash") == 0) {
-            full_struct_sym = "cfish_Hash";
-            vtable_var      = "CFISH_HASH";
-        }
-        else if (strcmp(full_struct_sym, "lucy_Obj") == 0) {
-            full_struct_sym = "cfish_Obj";
-            vtable_var      = "CFISH_OBJ";
-        }
-        else if (strcmp(full_struct_sym, "lucy_VArray") == 0) {
-            full_struct_sym = "cfish_VArray";
-            vtable_var      = "CFISH_VARRAY";
-        }
-        else if (strcmp(full_struct_sym, "lucy_VTable") == 0) {
-            full_struct_sym = "cfish_VTable";
-            vtable_var      = "CFISH_VTABLE";
-        }
-
         start = CFCUtil_cat(start, full_struct_sym, "*\t", vtable_var, "_\n",
                             NULL);
         input = CFCUtil_cat(input, vtable_var, "_\n"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/ByteBuf.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/ByteBuf.c b/clownfish/runtime/core/Clownfish/ByteBuf.c
index 1c48214..685faf1 100644
--- a/clownfish/runtime/core/Clownfish/ByteBuf.c
+++ b/clownfish/runtime/core/Clownfish/ByteBuf.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_BYTEBUF
-#define C_LUCY_VIEWBYTEBUF
+#define C_CFISH_BYTEBUF
+#define C_CFISH_VIEWBYTEBUF
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/CharBuf.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/CharBuf.c b/clownfish/runtime/core/Clownfish/CharBuf.c
index 9953dc6..0e19c83 100644
--- a/clownfish/runtime/core/Clownfish/CharBuf.c
+++ b/clownfish/runtime/core/Clownfish/CharBuf.c
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#define C_LUCY_CHARBUF
-#define C_LUCY_VIEWCHARBUF
-#define C_LUCY_ZOMBIECHARBUF
+#define C_CFISH_CHARBUF
+#define C_CFISH_VIEWCHARBUF
+#define C_CFISH_ZOMBIECHARBUF
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Err.c b/clownfish/runtime/core/Clownfish/Err.c
index ee9f930..c933137 100644
--- a/clownfish/runtime/core/Clownfish/Err.c
+++ b/clownfish/runtime/core/Clownfish/Err.c
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#define C_LUCY_ERR
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
+#define C_CFISH_ERR
+#define C_CFISH_OBJ
+#define C_CFISH_VTABLE
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Hash.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Hash.c b/clownfish/runtime/core/Clownfish/Hash.c
index 1e2cd56..57c8ee5 100644
--- a/clownfish/runtime/core/Clownfish/Hash.c
+++ b/clownfish/runtime/core/Clownfish/Hash.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_HASH
-#define C_LUCY_HASHTOMBSTONE
+#define C_CFISH_HASH
+#define C_CFISH_HASHTOMBSTONE
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/LockFreeRegistry.c b/clownfish/runtime/core/Clownfish/LockFreeRegistry.c
index 519dc51..c31e118 100644
--- a/clownfish/runtime/core/Clownfish/LockFreeRegistry.c
+++ b/clownfish/runtime/core/Clownfish/LockFreeRegistry.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_LOCKFREEREGISTRY
+#define C_CFISH_LOCKFREEREGISTRY
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Method.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Method.c b/clownfish/runtime/core/Clownfish/Method.c
index 13f3abb..96979da 100644
--- a/clownfish/runtime/core/Clownfish/Method.c
+++ b/clownfish/runtime/core/Clownfish/Method.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_METHOD
+#define C_CFISH_METHOD
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Num.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Num.c b/clownfish/runtime/core/Clownfish/Num.c
index bc84c30..462ad18 100644
--- a/clownfish/runtime/core/Clownfish/Num.c
+++ b/clownfish/runtime/core/Clownfish/Num.c
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-#define C_LUCY_NUM
-#define C_LUCY_INTNUM
-#define C_LUCY_FLOATNUM
-#define C_LUCY_INTEGER32
-#define C_LUCY_INTEGER64
-#define C_LUCY_FLOAT32
-#define C_LUCY_FLOAT64
-#define C_LUCY_BOOLNUM
-#define C_LUCY_VIEWCHARBUF
+#define C_CFISH_NUM
+#define C_CFISH_INTNUM
+#define C_CFISH_FLOATNUM
+#define C_CFISH_INTEGER32
+#define C_CFISH_INTEGER64
+#define C_CFISH_FLOAT32
+#define C_CFISH_FLOAT64
+#define C_CFISH_BOOLNUM
+#define C_CFISH_VIEWCHARBUF
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Obj.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Obj.c b/clownfish/runtime/core/Clownfish/Obj.c
index bb1b3cb..c6b8712 100644
--- a/clownfish/runtime/core/Clownfish/Obj.c
+++ b/clownfish/runtime/core/Clownfish/Obj.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
+#define C_CFISH_OBJ
+#define C_CFISH_VTABLE
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test.c b/clownfish/runtime/core/Clownfish/Test.c
index 14573b8..20f9c78 100644
--- a/clownfish/runtime/core/Clownfish/Test.c
+++ b/clownfish/runtime/core/Clownfish/Test.c
@@ -18,7 +18,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define C_LUCY_TESTBATCH
+#define C_CFISH_TESTBATCH
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/TestByteBuf.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/TestByteBuf.c b/clownfish/runtime/core/Clownfish/Test/TestByteBuf.c
index c411753..c8506b3 100644
--- a/clownfish/runtime/core/Clownfish/Test/TestByteBuf.c
+++ b/clownfish/runtime/core/Clownfish/Test/TestByteBuf.c
@@ -17,6 +17,7 @@
 #include <string.h>
 
 #define C_LUCY_TESTBYTEBUF
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/TestCharBuf.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/TestCharBuf.c b/clownfish/runtime/core/Clownfish/Test/TestCharBuf.c
index afefbea..122d0c4 100644
--- a/clownfish/runtime/core/Clownfish/Test/TestCharBuf.c
+++ b/clownfish/runtime/core/Clownfish/Test/TestCharBuf.c
@@ -18,6 +18,7 @@
 #include <stdio.h>
 
 #define C_LUCY_TESTCHARBUF
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/TestErr.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/TestErr.c b/clownfish/runtime/core/Clownfish/Test/TestErr.c
index 26255a8..4ee3f06 100644
--- a/clownfish/runtime/core/Clownfish/Test/TestErr.c
+++ b/clownfish/runtime/core/Clownfish/Test/TestErr.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/TestHash.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/TestHash.c b/clownfish/runtime/core/Clownfish/Test/TestHash.c
index 4f28765..00da68f 100644
--- a/clownfish/runtime/core/Clownfish/Test/TestHash.c
+++ b/clownfish/runtime/core/Clownfish/Test/TestHash.c
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <time.h>
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/TestLockFreeRegistry.c b/clownfish/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
index 0323f61..716d4d9 100644
--- a/clownfish/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
+++ b/clownfish/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
@@ -16,6 +16,7 @@
 
 #include <string.h>
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/TestNum.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/TestNum.c b/clownfish/runtime/core/Clownfish/Test/TestNum.c
index f2c3252..00721ce 100644
--- a/clownfish/runtime/core/Clownfish/Test/TestNum.c
+++ b/clownfish/runtime/core/Clownfish/Test/TestNum.c
@@ -16,6 +16,7 @@
 
 #define C_LUCY_TESTNUM
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/TestObj.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/TestObj.c b/clownfish/runtime/core/Clownfish/Test/TestObj.c
index 4d7c76b..b2a4414 100644
--- a/clownfish/runtime/core/Clownfish/Test/TestObj.c
+++ b/clownfish/runtime/core/Clownfish/Test/TestObj.c
@@ -17,6 +17,7 @@
 #include <stdio.h>
 
 #define C_LUCY_TESTOBJ
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/TestUtils.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/TestUtils.c b/clownfish/runtime/core/Clownfish/Test/TestUtils.c
index 4a39702..db1000a 100644
--- a/clownfish/runtime/core/Clownfish/Test/TestUtils.c
+++ b/clownfish/runtime/core/Clownfish/Test/TestUtils.c
@@ -18,6 +18,7 @@
 #include <stdlib.h>
 
 #define C_LUCY_TESTUTILS
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/TestVArray.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/TestVArray.c b/clownfish/runtime/core/Clownfish/Test/TestVArray.c
index 5d6a69d..b30d7b1 100644
--- a/clownfish/runtime/core/Clownfish/Test/TestVArray.c
+++ b/clownfish/runtime/core/Clownfish/Test/TestVArray.c
@@ -17,6 +17,7 @@
 #include <string.h>
 
 #define C_LUCY_TESTVARRAY
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/Util/TestAtomic.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/Util/TestAtomic.c b/clownfish/runtime/core/Clownfish/Test/Util/TestAtomic.c
index 7d0b978..9adae1c 100644
--- a/clownfish/runtime/core/Clownfish/Test/Util/TestAtomic.c
+++ b/clownfish/runtime/core/Clownfish/Test/Util/TestAtomic.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/Util/TestMemory.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/Util/TestMemory.c b/clownfish/runtime/core/Clownfish/Test/Util/TestMemory.c
index 7481b66..65c5850 100644
--- a/clownfish/runtime/core/Clownfish/Test/Util/TestMemory.c
+++ b/clownfish/runtime/core/Clownfish/Test/Util/TestMemory.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/Util/TestNumberUtils.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/Util/TestNumberUtils.c b/clownfish/runtime/core/Clownfish/Test/Util/TestNumberUtils.c
index c662e8e..66db928 100644
--- a/clownfish/runtime/core/Clownfish/Test/Util/TestNumberUtils.c
+++ b/clownfish/runtime/core/Clownfish/Test/Util/TestNumberUtils.c
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <time.h>
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Test/Util/TestStringHelper.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Test/Util/TestStringHelper.c b/clownfish/runtime/core/Clownfish/Test/Util/TestStringHelper.c
index be05145..08a9d72 100644
--- a/clownfish/runtime/core/Clownfish/Test/Util/TestStringHelper.c
+++ b/clownfish/runtime/core/Clownfish/Test/Util/TestStringHelper.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Util/Atomic.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Util/Atomic.c b/clownfish/runtime/core/Clownfish/Util/Atomic.c
index 62c43e2..e950c4b 100644
--- a/clownfish/runtime/core/Clownfish/Util/Atomic.c
+++ b/clownfish/runtime/core/Clownfish/Util/Atomic.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_ATOMIC
+#define C_CFISH_ATOMIC
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #include "Clownfish/Util/Atomic.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Util/Memory.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Util/Memory.c b/clownfish/runtime/core/Clownfish/Util/Memory.c
index 0f52e98..9a36d1b 100644
--- a/clownfish/runtime/core/Clownfish/Util/Memory.c
+++ b/clownfish/runtime/core/Clownfish/Util/Memory.c
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#define C_LUCY_MEMORY
+#define C_CFISH_MEMORY
 #include <stdlib.h>
 #include <stdio.h>
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 #include "Clownfish/Util/Memory.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Util/NumberUtils.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Util/NumberUtils.c b/clownfish/runtime/core/Clownfish/Util/NumberUtils.c
index ba73cf9..12f3a23 100644
--- a/clownfish/runtime/core/Clownfish/Util/NumberUtils.c
+++ b/clownfish/runtime/core/Clownfish/Util/NumberUtils.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_NUMBERUTILS
+#define C_CFISH_NUMBERUTILS
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Util/SortUtils.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Util/SortUtils.c b/clownfish/runtime/core/Clownfish/Util/SortUtils.c
index 3b17077..4efd5ef 100644
--- a/clownfish/runtime/core/Clownfish/Util/SortUtils.c
+++ b/clownfish/runtime/core/Clownfish/Util/SortUtils.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_SORTUTILS
+#define C_CFISH_SORTUTILS
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/Util/StringHelper.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/Util/StringHelper.c b/clownfish/runtime/core/Clownfish/Util/StringHelper.c
index 58f278d..185b6a2 100644
--- a/clownfish/runtime/core/Clownfish/Util/StringHelper.c
+++ b/clownfish/runtime/core/Clownfish/Util/StringHelper.c
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#define C_LUCY_STRINGHELPER
+#define C_CFISH_STRINGHELPER
 #include <string.h>
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/VArray.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/VArray.c b/clownfish/runtime/core/Clownfish/VArray.c
index c9b6e47..cc7806a 100644
--- a/clownfish/runtime/core/Clownfish/VArray.c
+++ b/clownfish/runtime/core/Clownfish/VArray.c
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#define C_LUCY_VARRAY
+#define C_CFISH_VARRAY
 #include <string.h>
 #include <stdlib.h>
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/core/Clownfish/VTable.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/core/Clownfish/VTable.c b/clownfish/runtime/core/Clownfish/VTable.c
index 0ff58e2..c91aa03 100644
--- a/clownfish/runtime/core/Clownfish/VTable.c
+++ b/clownfish/runtime/core/Clownfish/VTable.c
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#define C_LUCY_VTABLE
-#define C_LUCY_OBJ
-#define C_LUCY_CHARBUF
-#define C_LUCY_METHOD
+#define C_CFISH_VTABLE
+#define C_CFISH_OBJ
+#define C_CFISH_CHARBUF
+#define C_CFISH_METHOD
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/clownfish/runtime/perl/xs/XSBind.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/perl/xs/XSBind.c b/clownfish/runtime/perl/xs/XSBind.c
index 70db4da..d47c484 100644
--- a/clownfish/runtime/perl/xs/XSBind.c
+++ b/clownfish/runtime/perl/xs/XSBind.c
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
-#define C_LUCY_LOCKFREEREGISTRY
+#define C_CFISH_OBJ
+#define C_CFISH_VTABLE
+#define C_CFISH_LOCKFREEREGISTRY
 #define NEED_newRV_noinc
 #include "XSBind.h"
 #include "Clownfish/LockFreeRegistry.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish.cfp
----------------------------------------------------------------------
diff --git a/core/Clownfish.cfp b/core/Clownfish.cfp
new file mode 100644
index 0000000..ae91f8a
--- /dev/null
+++ b/core/Clownfish.cfp
@@ -0,0 +1,5 @@
+{
+    "name": "Clownfish",
+    "nickname": "Cfish",
+    "version": "v0.3.0"
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/ByteBuf.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/ByteBuf.c b/core/Clownfish/ByteBuf.c
index 3bcc12d..bbd0484 100644
--- a/core/Clownfish/ByteBuf.c
+++ b/core/Clownfish/ByteBuf.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_BYTEBUF
-#define C_LUCY_VIEWBYTEBUF
+#define C_CFISH_BYTEBUF
+#define C_CFISH_VIEWBYTEBUF
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/ByteBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/ByteBuf.cfh b/core/Clownfish/ByteBuf.cfh
index 6967d08..15b28f3 100644
--- a/core/Clownfish/ByteBuf.cfh
+++ b/core/Clownfish/ByteBuf.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /**
  * Growable buffer holding arbitrary bytes.

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/CharBuf.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/CharBuf.c b/core/Clownfish/CharBuf.c
index fda1646..23bf180 100644
--- a/core/Clownfish/CharBuf.c
+++ b/core/Clownfish/CharBuf.c
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#define C_LUCY_CHARBUF
-#define C_LUCY_VIEWCHARBUF
-#define C_LUCY_ZOMBIECHARBUF
+#define C_CFISH_CHARBUF
+#define C_CFISH_VIEWCHARBUF
+#define C_CFISH_ZOMBIECHARBUF
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/CharBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/CharBuf.cfh b/core/Clownfish/CharBuf.cfh
index 6eeca16..2601f6a 100644
--- a/core/Clownfish/CharBuf.cfh
+++ b/core/Clownfish/CharBuf.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /**
  * Growable buffer holding Unicode characters.
@@ -395,7 +395,7 @@ __C__
 #define CFISH_ZCB_WRAP_STR(ptr, size) \
     cfish_ZCB_wrap_str(alloca(cfish_ZCB_size()), ptr, size)
 
-#ifdef LUCY_USE_SHORT_NAMES
+#ifdef CFISH_USE_SHORT_NAMES
   #define ZCB_BLANK             CFISH_ZCB_BLANK
   #define ZCB_WRAP              CFISH_ZCB_WRAP
   #define ZCB_WRAP_STR          CFISH_ZCB_WRAP_STR

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Err.c b/core/Clownfish/Err.c
index 0a6e979..f6d395d 100644
--- a/core/Clownfish/Err.c
+++ b/core/Clownfish/Err.c
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#define C_LUCY_ERR
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
+#define C_CFISH_ERR
+#define C_CFISH_OBJ
+#define C_CFISH_VTABLE
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Err.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Err.cfh b/core/Clownfish/Err.cfh
index 80ca136..7bc4f86 100644
--- a/core/Clownfish/Err.cfh
+++ b/core/Clownfish/Err.cfh
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 __C__
 typedef void 
 (*Cfish_Err_Attempt_t)(void *context);
 
-#ifdef LUCY_USE_SHORT_NAMES
+#ifdef CFISH_USE_SHORT_NAMES
   #define Err_Attempt_t Cfish_Err_Attempt_t
 #endif
 __END_C__
@@ -241,7 +241,7 @@ cfish_Err_abstract_class_check(cfish_Obj *obj, cfish_VTable *vtable) {
 #define CFISH_ABSTRACT_CLASS_CHECK(_obj, _vtable) \
     cfish_Err_abstract_class_check(((cfish_Obj*)_obj), _vtable)
 
-#ifdef LUCY_USE_SHORT_NAMES
+#ifdef CFISH_USE_SHORT_NAMES
   #define THROW                 CFISH_THROW
   #define RETHROW               CFISH_RETHROW
   #define WARN                  CFISH_WARN

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Hash.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Hash.c b/core/Clownfish/Hash.c
index 59c4854..b85683b 100644
--- a/core/Clownfish/Hash.c
+++ b/core/Clownfish/Hash.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_HASH
-#define C_LUCY_HASHTOMBSTONE
+#define C_CFISH_HASH
+#define C_CFISH_HASHTOMBSTONE
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Hash.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Hash.cfh b/core/Clownfish/Hash.cfh
index 787184f..5724883 100644
--- a/core/Clownfish/Hash.cfh
+++ b/core/Clownfish/Hash.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /**
  * Hashtable.

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/LockFreeRegistry.c b/core/Clownfish/LockFreeRegistry.c
index 11ab071..ccf3c30 100644
--- a/core/Clownfish/LockFreeRegistry.c
+++ b/core/Clownfish/LockFreeRegistry.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_LOCKFREEREGISTRY
+#define C_CFISH_LOCKFREEREGISTRY
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/LockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/LockFreeRegistry.cfh b/core/Clownfish/LockFreeRegistry.cfh
index 18ac4bb..2a3d62a 100644
--- a/core/Clownfish/LockFreeRegistry.cfh
+++ b/core/Clownfish/LockFreeRegistry.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /** Specialized lock free hash table for storing VTables.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Method.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Method.c b/core/Clownfish/Method.c
index 8a76d2b..9d36299 100644
--- a/core/Clownfish/Method.c
+++ b/core/Clownfish/Method.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_METHOD
+#define C_CFISH_METHOD
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Method.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Method.cfh b/core/Clownfish/Method.cfh
index 17df64a..5cac0b2 100644
--- a/core/Clownfish/Method.cfh
+++ b/core/Clownfish/Method.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /** Method metadata.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Num.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Num.c b/core/Clownfish/Num.c
index e40f825..7dcc0dd 100644
--- a/core/Clownfish/Num.c
+++ b/core/Clownfish/Num.c
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-#define C_LUCY_NUM
-#define C_LUCY_INTNUM
-#define C_LUCY_FLOATNUM
-#define C_LUCY_INTEGER32
-#define C_LUCY_INTEGER64
-#define C_LUCY_FLOAT32
-#define C_LUCY_FLOAT64
-#define C_LUCY_BOOLNUM
-#define C_LUCY_VIEWCHARBUF
+#define C_CFISH_NUM
+#define C_CFISH_INTNUM
+#define C_CFISH_FLOATNUM
+#define C_CFISH_INTEGER32
+#define C_CFISH_INTEGER64
+#define C_CFISH_FLOAT32
+#define C_CFISH_FLOAT64
+#define C_CFISH_BOOLNUM
+#define C_CFISH_VIEWCHARBUF
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Num.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Num.cfh b/core/Clownfish/Num.cfh
index a684fe1..51f28e9 100644
--- a/core/Clownfish/Num.cfh
+++ b/core/Clownfish/Num.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /** Abstract base class for numbers.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Obj.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Obj.c b/core/Clownfish/Obj.c
index a805910..fd943c6 100644
--- a/core/Clownfish/Obj.c
+++ b/core/Clownfish/Obj.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
+#define C_CFISH_OBJ
+#define C_CFISH_VTABLE
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Obj.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Obj.cfh b/core/Clownfish/Obj.cfh
index a7370fb..55e10cd 100644
--- a/core/Clownfish/Obj.cfh
+++ b/core/Clownfish/Obj.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /** Base class for all objects.
  */
@@ -213,7 +213,7 @@ cfish_Obj_decref(cfish_Obj *self) {
 
 #define CFISH_DECREF(_self) cfish_Obj_decref((cfish_Obj*)_self)
 
-#ifdef LUCY_USE_SHORT_NAMES
+#ifdef CFISH_USE_SHORT_NAMES
   #define SUPER_DESTROY(_self, _vtable)   CFISH_SUPER_DESTROY(_self, _vtable)
   #define INCREF(_self)                   CFISH_INCREF(_self)
   #define DECREF(_self)                   CFISH_DECREF(_self)

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Test/TestBatch.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestBatch.c b/core/Clownfish/Test/TestBatch.c
index 403c224..f77a71a 100644
--- a/core/Clownfish/Test/TestBatch.c
+++ b/core/Clownfish/Test/TestBatch.c
@@ -18,7 +18,8 @@
 #include <stdio.h>
 #include <string.h>
 
-#define C_LUCY_TESTBATCH
+#define C_CFISH_TESTBATCH
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #include "Clownfish/Test/TestBatch.h"
 #include "Clownfish/CharBuf.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Test/TestBatch.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestBatch.cfh b/core/Clownfish/Test/TestBatch.cfh
index 42b84cb..01113a0 100644
--- a/core/Clownfish/Test/TestBatch.cfh
+++ b/core/Clownfish/Test/TestBatch.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 abstract class Clownfish::Test::TestBatch inherits Clownfish::Obj {
     TestFormatter *formatter;

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Test/TestFormatter.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestFormatter.c b/core/Clownfish/Test/TestFormatter.c
index 6bccc14..5a700a2 100644
--- a/core/Clownfish/Test/TestFormatter.c
+++ b/core/Clownfish/Test/TestFormatter.c
@@ -16,7 +16,8 @@
 
 #include <stdio.h>
 
-#define C_LUCY_TESTFORMATTER
+#define C_CFISH_TESTFORMATTER
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Test/TestFormatter.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestFormatter.cfh b/core/Clownfish/Test/TestFormatter.cfh
index 4487b37..2ba63bf 100644
--- a/core/Clownfish/Test/TestFormatter.cfh
+++ b/core/Clownfish/Test/TestFormatter.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /**
  * Abstract base class for Clownfish test formatters.

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Test/TestRunner.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestRunner.c b/core/Clownfish/Test/TestRunner.c
index 0779e5d..8091c36 100644
--- a/core/Clownfish/Test/TestRunner.c
+++ b/core/Clownfish/Test/TestRunner.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTRUNNER
+#define C_CFISH_TESTRUNNER
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Test/TestRunner.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestRunner.cfh b/core/Clownfish/Test/TestRunner.cfh
index 61a951c..a59010a 100644
--- a/core/Clownfish/Test/TestRunner.cfh
+++ b/core/Clownfish/Test/TestRunner.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /**
  * Run multiple test batches and collect statistics.

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/Atomic.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/Atomic.c b/core/Clownfish/Util/Atomic.c
index 8bf776a..83ca2bd 100644
--- a/core/Clownfish/Util/Atomic.c
+++ b/core/Clownfish/Util/Atomic.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_ATOMIC
+#define C_CFISH_ATOMIC
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #include "Clownfish/Util/Atomic.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/Atomic.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/Atomic.cfh b/core/Clownfish/Util/Atomic.cfh
index da741ce..d9d20c4 100644
--- a/core/Clownfish/Util/Atomic.cfh
+++ b/core/Clownfish/Util/Atomic.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /** Provide atomic memory operations.
  */
@@ -100,7 +100,7 @@ cfish_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
 
 #endif // Big platform if-else chain.
 
-#ifdef LUCY_USE_SHORT_NAMES
+#ifdef CFISH_USE_SHORT_NAMES
   #define Atomic_cas_ptr cfish_Atomic_cas_ptr
 #endif
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/Memory.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/Memory.c b/core/Clownfish/Util/Memory.c
index 0f52e98..9a36d1b 100644
--- a/core/Clownfish/Util/Memory.c
+++ b/core/Clownfish/Util/Memory.c
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#define C_LUCY_MEMORY
+#define C_CFISH_MEMORY
 #include <stdlib.h>
 #include <stdio.h>
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 #include "Clownfish/Util/Memory.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/Memory.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/Memory.cfh b/core/Clownfish/Util/Memory.cfh
index e5ed310..93df35d 100644
--- a/core/Clownfish/Util/Memory.cfh
+++ b/core/Clownfish/Util/Memory.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 inert class Clownfish::Util::Memory {
 
@@ -61,7 +61,7 @@ __C__
 #define CFISH_REALLOCATE   cfish_Memory_wrapped_realloc
 #define CFISH_FREEMEM      cfish_Memory_wrapped_free
 
-#ifdef LUCY_USE_SHORT_NAMES
+#ifdef CFISH_USE_SHORT_NAMES
   #define MALLOCATE                       CFISH_MALLOCATE
   #define CALLOCATE                       CFISH_CALLOCATE
   #define REALLOCATE                      CFISH_REALLOCATE

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/NumberUtils.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/NumberUtils.c b/core/Clownfish/Util/NumberUtils.c
index ba73cf9..12f3a23 100644
--- a/core/Clownfish/Util/NumberUtils.c
+++ b/core/Clownfish/Util/NumberUtils.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_NUMBERUTILS
+#define C_CFISH_NUMBERUTILS
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/NumberUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/NumberUtils.cfh b/core/Clownfish/Util/NumberUtils.cfh
index e94b90c..cd6c750 100644
--- a/core/Clownfish/Util/NumberUtils.cfh
+++ b/core/Clownfish/Util/NumberUtils.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /** Provide various number-related utilies.
  *
@@ -464,7 +464,7 @@ cfish_NumUtil_u4set(void *array, uint32_t tick, uint8_t value) {
     ints[(tick >> 1)]  = (ints[(tick >> 1)] & ~mask) | new_bits;
 }
 
-#ifdef LUCY_USE_SHORT_NAMES
+#ifdef CFISH_USE_SHORT_NAMES
   #define C32_MAX_BYTES                CFISH_NUMUTIL_C32_MAX_BYTES
   #define C64_MAX_BYTES                CFISH_NUMUTIL_C64_MAX_BYTES
 #endif

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/SortUtils.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/SortUtils.c b/core/Clownfish/Util/SortUtils.c
index 18eb88d..1a97413 100644
--- a/core/Clownfish/Util/SortUtils.c
+++ b/core/Clownfish/Util/SortUtils.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_SORTUTILS
+#define C_CFISH_SORTUTILS
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/SortUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/SortUtils.cfh b/core/Clownfish/Util/SortUtils.cfh
index 7667e81..39ac2d1 100644
--- a/core/Clownfish/Util/SortUtils.cfh
+++ b/core/Clownfish/Util/SortUtils.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 __C__
 typedef int

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/StringHelper.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/StringHelper.c b/core/Clownfish/Util/StringHelper.c
index 7726f9d..764be2b 100644
--- a/core/Clownfish/Util/StringHelper.c
+++ b/core/Clownfish/Util/StringHelper.c
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#define C_LUCY_STRINGHELPER
+#define C_CFISH_STRINGHELPER
 #include <string.h>
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/Util/StringHelper.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Util/StringHelper.cfh b/core/Clownfish/Util/StringHelper.cfh
index 9d7f4e0..482666f 100644
--- a/core/Clownfish/Util/StringHelper.cfh
+++ b/core/Clownfish/Util/StringHelper.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 inert class Clownfish::Util::StringHelper cnick StrHelp {
 
@@ -75,7 +75,7 @@ __C__
  * terminating NULL.
  */
 #define cfish_StrHelp_MAX_BASE36_BYTES 14
-#ifdef LUCY_USE_SHORT_NAMES
+#ifdef CFISH_USE_SHORT_NAMES
   #define StrHelp_MAX_BASE36_BYTES cfish_StrHelp_MAX_BASE36_BYTES
 #endif
 __END_C__

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/VArray.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/VArray.c b/core/Clownfish/VArray.c
index 7da0d33..38aa128 100644
--- a/core/Clownfish/VArray.c
+++ b/core/Clownfish/VArray.c
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#define C_LUCY_VARRAY
+#define C_CFISH_VARRAY
 #include <string.h>
 #include <stdlib.h>
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/VArray.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/VArray.cfh b/core/Clownfish/VArray.cfh
index f36e31d..f64b8b5 100644
--- a/core/Clownfish/VArray.cfh
+++ b/core/Clownfish/VArray.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 __C__
 #include "Clownfish/Util/SortUtils.h"
@@ -22,7 +22,7 @@ __C__
 typedef bool
 (*Cfish_VA_Gather_Test_t)(cfish_VArray *self, uint32_t tick, void *data);
 
-#ifdef LUCY_USE_SHORT_NAMES
+#ifdef CFISH_USE_SHORT_NAMES
   #define VA_Gather_Test_t Cfish_VA_Gather_Test_t
 #endif
 __END_C__

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/VTable.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/VTable.c b/core/Clownfish/VTable.c
index dbc5715..3bd393b 100644
--- a/core/Clownfish/VTable.c
+++ b/core/Clownfish/VTable.c
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#define C_LUCY_VTABLE
-#define C_LUCY_OBJ
-#define C_LUCY_CHARBUF
-#define C_LUCY_METHOD
+#define C_CFISH_VTABLE
+#define C_CFISH_OBJ
+#define C_CFISH_CHARBUF
+#define C_CFISH_METHOD
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Clownfish/VTable.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/VTable.cfh b/core/Clownfish/VTable.cfh
index 9f2555d..1325fd4 100644
--- a/core/Clownfish/VTable.cfh
+++ b/core/Clownfish/VTable.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel Clownfish;
 
 /** Virtual method dispatch table.
  *

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Lucy.c
----------------------------------------------------------------------
diff --git a/core/Lucy.c b/core/Lucy.c
index 3ed569c..ebd0c0b 100644
--- a/core/Lucy.c
+++ b/core/Lucy.c
@@ -20,8 +20,8 @@
 
 void
 lucy_init_parcel() {
-    lucy_Bool_init_class();
-    lucy_Hash_init_class();
-    lucy_Err_init_class();
+    cfish_Bool_init_class();
+    cfish_Hash_init_class();
+    cfish_Err_init_class();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Lucy/Search/Matcher.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Search/Matcher.c b/core/Lucy/Search/Matcher.c
index 79673a3..c8ea31a 100644
--- a/core/Lucy/Search/Matcher.c
+++ b/core/Lucy/Search/Matcher.c
@@ -15,6 +15,7 @@
  */
 
 #define C_LUCY_MATCHER
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Lucy/Search/QueryParser.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Search/QueryParser.c b/core/Lucy/Search/QueryParser.c
index d6e1110..b665f73 100644
--- a/core/Lucy/Search/QueryParser.c
+++ b/core/Lucy/Search/QueryParser.c
@@ -15,7 +15,7 @@
  */
 
 #define C_LUCY_QUERYPARSER
-#define C_LUCY_VIEWCHARBUF
+#define C_CFISH_VIEWCHARBUF
 #include <stdlib.h>
 #include <ctype.h>
 #include "Lucy/Util/ToolSet.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Lucy/Util/Debug.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Util/Debug.c b/core/Lucy/Util/Debug.c
index 773aaa9..aa88c7e 100644
--- a/core/Lucy/Util/Debug.c
+++ b/core/Lucy/Util/Debug.c
@@ -15,6 +15,7 @@
  */
 
 #define C_LUCY_DEBUG
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/core/Lucy/Util/ToolSet.h
----------------------------------------------------------------------
diff --git a/core/Lucy/Util/ToolSet.h b/core/Lucy/Util/ToolSet.h
index a21fb1e..6ad0ebf 100644
--- a/core/Lucy/Util/ToolSet.h
+++ b/core/Lucy/Util/ToolSet.h
@@ -28,6 +28,7 @@ extern "C" {
  * header files, so that the header files remain as sparse as possible.
  */
 
+#define CFISH_USE_SHORT_NAMES
 #define LUCY_USE_SHORT_NAMES
 #define CHY_USE_SHORT_NAMES
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/example-lang/src/Lucy/Object/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/example-lang/src/Lucy/Object/LockFreeRegistry.c b/example-lang/src/Lucy/Object/LockFreeRegistry.c
index 1f208c4..5991ad3 100644
--- a/example-lang/src/Lucy/Object/LockFreeRegistry.c
+++ b/example-lang/src/Lucy/Object/LockFreeRegistry.c
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define C_LUCY_LOCKFREEREGISTRY
+#define C_CFISH_LOCKFREEREGISTRY
 
 #include "CFBind.h"
 #include "Clownfish/LockFreeRegistry.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/example-lang/src/Lucy/Object/Obj.c
----------------------------------------------------------------------
diff --git a/example-lang/src/Lucy/Object/Obj.c b/example-lang/src/Lucy/Object/Obj.c
index e529513..2e0551d 100644
--- a/example-lang/src/Lucy/Object/Obj.c
+++ b/example-lang/src/Lucy/Object/Obj.c
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define C_LUCY_OBJ
+#define C_CFISH_OBJ
 
 #include "CFBind.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/example-lang/src/Lucy/Object/VTable.c
----------------------------------------------------------------------
diff --git a/example-lang/src/Lucy/Object/VTable.c b/example-lang/src/Lucy/Object/VTable.c
index 00c9901..3055f8d 100644
--- a/example-lang/src/Lucy/Object/VTable.c
+++ b/example-lang/src/Lucy/Object/VTable.c
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
+#define C_CFISH_OBJ
+#define C_CFISH_VTABLE
 
 #include "CFBind.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/perl/buildlib/Lucy/Build/Binding/Object.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Object.pm b/perl/buildlib/Lucy/Build/Binding/Object.pm
index 0ba0bb6..210db4f 100644
--- a/perl/buildlib/Lucy/Build/Binding/Object.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Object.pm
@@ -110,7 +110,7 @@ OUTPUT: RETVAL
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::ByteBuf",
     );
     $binding->append_xs($xs_code);
@@ -180,7 +180,7 @@ OUTPUT: RETVAL
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::CharBuf",
     );
     $binding->append_xs($xs_code);
@@ -228,7 +228,7 @@ OUTPUT: RETVAL
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::Err",
     );
     $binding->bind_constructor( alias => '_new' );
@@ -298,7 +298,7 @@ PPCODE:
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::Hash",
     );
     $binding->exclude_method($_) for @hand_rolled;
@@ -385,7 +385,7 @@ END_XS_CODE
 
 sub bind_lockfreeregistry {
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::LockFreeRegistry",
     );
     Clownfish::CFC::Binding::Perl::Class->register($binding);
@@ -409,7 +409,7 @@ OUTPUT: RETVAL
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::Float32",
     );
     $binding->append_xs($float32_xs_code);
@@ -436,7 +436,7 @@ OUTPUT: RETVAL
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::Float64",
     );
     $binding->append_xs($float64_xs_code);
@@ -634,7 +634,7 @@ PPCODE:
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::Obj",
     );
     $binding->bind_method( alias => '_load', method => 'Load' );
@@ -724,7 +724,7 @@ OUTPUT: RETVAL
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::VArray",
     );
     $binding->exclude_method($_) for @hand_rolled;
@@ -781,7 +781,7 @@ OUTPUT: RETVAL
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::VTable",
     );
     $binding->exclude_method($_) for @hand_rolled;

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/perl/buildlib/Lucy/Build/Binding/Util.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Util.pm b/perl/buildlib/Lucy/Build/Binding/Util.pm
index 45b9ab4..186c517 100644
--- a/perl/buildlib/Lucy/Build/Binding/Util.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Util.pm
@@ -280,7 +280,7 @@ PPCODE:
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "Clownfish",
         class_name => "Clownfish::Util::StringHelper",
     );
     $binding->append_xs($xs_code);

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/perl/xs/XSBind.c
----------------------------------------------------------------------
diff --git a/perl/xs/XSBind.c b/perl/xs/XSBind.c
index 8352355..092b5e9 100644
--- a/perl/xs/XSBind.c
+++ b/perl/xs/XSBind.c
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
-#define C_LUCY_LOCKFREEREGISTRY
+#define C_CFISH_OBJ
+#define C_CFISH_VTABLE
+#define C_CFISH_LOCKFREEREGISTRY
 #define NEED_newRV_noinc
 #include "XSBind.h"
 #include "Clownfish/LockFreeRegistry.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/ruby/src/Lucy/Object/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/ruby/src/Lucy/Object/LockFreeRegistry.c b/ruby/src/Lucy/Object/LockFreeRegistry.c
index 1f208c4..5991ad3 100644
--- a/ruby/src/Lucy/Object/LockFreeRegistry.c
+++ b/ruby/src/Lucy/Object/LockFreeRegistry.c
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define C_LUCY_LOCKFREEREGISTRY
+#define C_CFISH_LOCKFREEREGISTRY
 
 #include "CFBind.h"
 #include "Clownfish/LockFreeRegistry.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/ruby/src/Lucy/Object/Obj.c
----------------------------------------------------------------------
diff --git a/ruby/src/Lucy/Object/Obj.c b/ruby/src/Lucy/Object/Obj.c
index e529513..2e0551d 100644
--- a/ruby/src/Lucy/Object/Obj.c
+++ b/ruby/src/Lucy/Object/Obj.c
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define C_LUCY_OBJ
+#define C_CFISH_OBJ
 
 #include "CFBind.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/05fa0688/ruby/src/Lucy/Object/VTable.c
----------------------------------------------------------------------
diff --git a/ruby/src/Lucy/Object/VTable.c b/ruby/src/Lucy/Object/VTable.c
index 00c9901..3055f8d 100644
--- a/ruby/src/Lucy/Object/VTable.c
+++ b/ruby/src/Lucy/Object/VTable.c
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
+#define C_CFISH_OBJ
+#define C_CFISH_VTABLE
 
 #include "CFBind.h"
 


[lucy-commits] [18/26] Move Lucy tests to a separate parcel TestLucy

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/TestMemoryPool.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestMemoryPool.cfh b/core/Lucy/Test/Util/TestMemoryPool.cfh
index 7cd1b9f..a0762e3 100644
--- a/core/Lucy/Test/Util/TestMemoryPool.cfh
+++ b/core/Lucy/Test/Util/TestMemoryPool.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Util::TestMemoryPool cnick TestMemPool
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/TestPriorityQueue.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestPriorityQueue.c b/core/Lucy/Test/Util/TestPriorityQueue.c
index a4a5a97..420f301 100644
--- a/core/Lucy/Test/Util/TestPriorityQueue.c
+++ b/core/Lucy/Test/Util/TestPriorityQueue.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTPRIORITYQUEUE
+#define C_TESTLUCY_TESTPRIORITYQUEUE
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/TestPriorityQueue.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestPriorityQueue.cfh b/core/Lucy/Test/Util/TestPriorityQueue.cfh
index 7fc7e56..19f56f5 100644
--- a/core/Lucy/Test/Util/TestPriorityQueue.cfh
+++ b/core/Lucy/Test/Util/TestPriorityQueue.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Util::NumPriorityQueue cnick NumPriQ
     inherits Lucy::Util::PriorityQueue {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/TestLucy.c
----------------------------------------------------------------------
diff --git a/core/TestLucy.c b/core/TestLucy.c
new file mode 100644
index 0000000..971dbae
--- /dev/null
+++ b/core/TestLucy.c
@@ -0,0 +1,20 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+void
+testlucy_init_parcel() {
+}
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/TestLucy.cfp
----------------------------------------------------------------------
diff --git a/core/TestLucy.cfp b/core/TestLucy.cfp
new file mode 100644
index 0000000..c1f2962
--- /dev/null
+++ b/core/TestLucy.cfp
@@ -0,0 +1,4 @@
+{
+    "name": "TestLucy",
+    "version": "v0.3.0"
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/perl/Build.PL
----------------------------------------------------------------------
diff --git a/perl/Build.PL b/perl/Build.PL
index d46e618..8c7307a 100644
--- a/perl/Build.PL
+++ b/perl/Build.PL
@@ -68,7 +68,9 @@ my $builder = Lucy::Build->new(
             $UTF8PROC_SRC_DIR,
         ],
     },
-    extra_compiler_flags => '-DCFP_CFISH -DCFP_TESTCFISH -DCFP_LUCY',
+    extra_compiler_flags => join( ' ', map { "-DCFP_$_" } qw(
+        CFISH TESTCFISH LUCY TESTLUCY
+    ) ),
     add_to_cleanup => [
         qw(
             Lucy-*

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/perl/buildlib/Lucy/Build/Binding/Misc.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Misc.pm b/perl/buildlib/Lucy/Build/Binding/Misc.pm
index 55b372a..e55382d 100644
--- a/perl/buildlib/Lucy/Build/Binding/Misc.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Misc.pm
@@ -117,7 +117,7 @@ CODE:
     cfish_CharBuf *class_name = cfish_CB_newf("%s", package);
     cfish_TestFormatter *formatter
         = (cfish_TestFormatter*)cfish_TestFormatterTAP_new();
-    bool result = lucy_Test_run_batch(class_name, formatter);
+    bool result = testlucy_Test_run_batch(class_name, formatter);
     CFISH_DECREF(class_name);
     CFISH_DECREF(formatter);
 
@@ -126,7 +126,7 @@ OUTPUT: RETVAL
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "TestLucy",
         class_name => "Lucy::Test",
     );
     $binding->append_xs($xs_code);
@@ -136,7 +136,7 @@ END_XS_CODE
 
 sub bind_testschema {
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "TestLucy",
         class_name => "Lucy::Test::TestSchema",
     );
     Clownfish::CFC::Binding::Perl::Class->register($binding);
@@ -153,10 +153,10 @@ MODULE = Lucy    PACKAGE = Lucy::Test::Util::BBSortEx
 
 SV*
 fetch(self)
-    lucy_BBSortEx *self;
+    testlucy_BBSortEx *self;
 CODE:
 {
-    void *address = Lucy_BBSortEx_Fetch(self);
+    void *address = TestLucy_BBSortEx_Fetch(self);
     if (address) {
         RETVAL = XSBind_cfish_to_perl(*(cfish_Obj**)address);
         CFISH_DECREF(*(cfish_Obj**)address);
@@ -169,10 +169,10 @@ OUTPUT: RETVAL
 
 SV*
 peek(self)
-    lucy_BBSortEx *self;
+    testlucy_BBSortEx *self;
 CODE:
 {
-    void *address = Lucy_BBSortEx_Peek(self);
+    void *address = TestLucy_BBSortEx_Peek(self);
     if (address) {
         RETVAL = XSBind_cfish_to_perl(*(cfish_Obj**)address);
     }
@@ -184,16 +184,16 @@ OUTPUT: RETVAL
 
 void
 feed(self, bb)
-    lucy_BBSortEx *self;
+    testlucy_BBSortEx *self;
     cfish_ByteBuf *bb;
 CODE:
     CFISH_INCREF(bb);
-    Lucy_BBSortEx_Feed(self, &bb);
+    TestLucy_BBSortEx_Feed(self, &bb);
 
 END_XS_CODE
 
     my $binding = Clownfish::CFC::Binding::Perl::Class->new(
-        parcel     => "Lucy",
+        parcel     => "TestLucy",
         class_name => "Lucy::Test::Util::BBSortEx",
     );
     $binding->exclude_method($_) for @hand_rolled;


[lucy-commits] [24/26] Rework Clownfish test harness

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestRunner.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestRunner.cfh b/core/Clownfish/TestHarness/TestRunner.cfh
deleted file mode 100644
index 8bebac0..0000000
--- a/core/Clownfish/TestHarness/TestRunner.cfh
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Clownfish;
-
-/**
- * Run multiple test batches and collect statistics.
- */
-class Clownfish::TestHarness::TestRunner inherits Clownfish::Obj {
-    TestFormatter *formatter;
-    uint32_t       num_tests;
-    uint32_t       num_tests_failed;
-    uint32_t       num_batches;
-    uint32_t       num_batches_failed;
-
-    inert incremented TestRunner*
-    new(TestFormatter *formatter);
-
-    /**
-     * @param formatter The test formatter to format the test output.
-     */
-    inert TestRunner*
-    init(TestRunner *self, TestFormatter *formatter);
-
-    public void
-    Destroy(TestRunner *self);
-
-    /** Run a test batch and collect statistics.
-     *
-     * @param batch The test batch.
-     * @return true if the test batch passed.
-     */
-    bool
-    Run_Batch(TestRunner *self, TestBatch *batch);
-
-    /** Print a summary after running all test batches.
-     *
-     * @return true if any tests were run and all test batches passed.
-     */
-    bool
-    Finish(TestRunner *self);
-
-    /** Return the number of tests run.
-     */
-    uint32_t
-    Get_Num_Tests(TestRunner *self);
-
-    /** Return the number of failed tests.
-     */
-    uint32_t
-    Get_Num_Tests_Failed(TestRunner *self);
-
-    /** Return the number of test batches run.
-     */
-    uint32_t
-    Get_Num_Batches(TestRunner *self);
-
-    /** Return the number of failed test batches.
-     */
-    uint32_t
-    Get_Num_Batches_Failed(TestRunner *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestSuite.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestSuite.c b/core/Clownfish/TestHarness/TestSuite.c
new file mode 100644
index 0000000..8ef8eb4
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestSuite.c
@@ -0,0 +1,109 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#define C_CFISH_TESTSUITE
+#define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/TestHarness/TestSuite.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestSuiteRunner.h"
+#include "Clownfish/VArray.h"
+#include "Clownfish/VTable.h"
+
+static void
+S_unbuffer_stdout();
+
+TestSuite*
+TestSuite_new() {
+    TestSuite *self = (TestSuite*)VTable_Make_Obj(TESTSUITE);
+    return TestSuite_init(self);
+}
+
+TestSuite*
+TestSuite_init(TestSuite *self) {
+    self->batches = VA_new(0);
+    return self;
+}
+
+void
+TestSuite_destroy(TestSuite *self) {
+    DECREF(self->batches);
+    SUPER_DESTROY(self, TESTSUITE);
+}
+
+void
+TestSuite_add_batch(TestSuite *self, TestBatch *batch) {
+    VA_Push(self->batches, (Obj*)batch);
+}
+
+bool
+TestSuite_run_batch(TestSuite *self, CharBuf *class_name,
+                    TestFormatter *formatter) {
+    S_unbuffer_stdout();
+
+    uint32_t size = VA_Get_Size(self->batches);
+
+    for (uint32_t i = 0; i < size; ++i) {
+        TestBatch *batch = (TestBatch*)VA_Fetch(self->batches, i);
+
+        if (CB_Equals(TestBatch_Get_Class_Name(batch), (Obj*)class_name)) {
+            TestBatchRunner *runner = TestBatchRunner_new(formatter);
+            bool result = TestBatchRunner_Run_Batch(runner, batch);
+            DECREF(runner);
+            return result;
+        }
+    }
+
+    THROW(ERR, "Couldn't find test class '%o'", class_name);
+    UNREACHABLE_RETURN(bool);
+}
+
+bool
+TestSuite_run_all_batches(TestSuite *self, TestFormatter *formatter) {
+    S_unbuffer_stdout();
+
+    TestSuiteRunner *runner = TestSuiteRunner_new(formatter);
+    uint32_t size = VA_Get_Size(self->batches);
+
+    for (uint32_t i = 0; i < size; ++i) {
+        TestBatch *batch = (TestBatch*)VA_Fetch(self->batches, i);
+        TestSuiteRunner_Run_Batch(runner, batch);
+    }
+
+    bool result = TestSuiteRunner_Finish(runner);
+
+    DECREF(runner);
+    return result;
+}
+
+static void
+S_unbuffer_stdout() {
+    int check_val = setvbuf(stdout, NULL, _IONBF, 0);
+    if (check_val != 0) {
+        fprintf(stderr, "Failed when trying to unbuffer stdout\n");
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestSuite.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestSuite.cfh b/core/Clownfish/TestHarness/TestSuite.cfh
new file mode 100644
index 0000000..4f1327a
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestSuite.cfh
@@ -0,0 +1,43 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Clownfish;
+
+/** Manage a collection of test batches.
+ */
+class Clownfish::TestHarness::TestSuite inherits Clownfish::Obj {
+    VArray *batches;
+
+    inert incremented TestSuite*
+    new();
+
+    inert TestSuite*
+    init(TestSuite *self);
+
+    public void
+    Destroy(TestSuite *self);
+
+    void
+    Add_Batch(TestSuite *self, decremented TestBatch *batch);
+
+    bool
+    Run_Batch(TestSuite *self, CharBuf *class_name, TestFormatter *formatter);
+
+    bool
+    Run_All_Batches(TestSuite *self, TestFormatter *formatter);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestSuiteRunner.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestSuiteRunner.c b/core/Clownfish/TestHarness/TestSuiteRunner.c
new file mode 100644
index 0000000..c2a9e72
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestSuiteRunner.c
@@ -0,0 +1,97 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define C_CFISH_TESTSUITERUNNER
+#define CFISH_USE_SHORT_NAMES
+#define LUCY_USE_SHORT_NAMES
+#define CHY_USE_SHORT_NAMES
+
+#include "Clownfish/TestHarness/TestSuiteRunner.h"
+
+#include "Clownfish/Err.h"
+#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/VTable.h"
+
+TestSuiteRunner*
+TestSuiteRunner_new(TestFormatter *formatter) {
+    TestSuiteRunner *self = (TestSuiteRunner*)VTable_Make_Obj(TESTSUITERUNNER);
+    return TestSuiteRunner_init(self, formatter);
+}
+
+TestSuiteRunner*
+TestSuiteRunner_init(TestSuiteRunner *self, TestFormatter *formatter) {
+    self->formatter          = (TestFormatter*)INCREF(formatter);
+    self->num_tests          = 0;
+    self->num_tests_failed   = 0;
+    self->num_batches        = 0;
+    self->num_batches_failed = 0;
+
+    return self;
+}
+
+void
+TestSuiteRunner_destroy(TestSuiteRunner *self) {
+    DECREF(self->formatter);
+    SUPER_DESTROY(self, TESTSUITERUNNER);
+}
+
+bool
+TestSuiteRunner_run_batch(TestSuiteRunner *self, TestBatch *batch) {
+    TestBatchRunner *batch_runner = TestBatchRunner_new(self->formatter);
+    bool success = TestBatchRunner_Run_Batch(batch_runner, batch);
+
+    self->num_tests        += TestBatchRunner_Get_Num_Tests(batch_runner);
+    self->num_tests_failed += TestBatchRunner_Get_Num_Failed(batch_runner);
+    self->num_batches      += 1;
+
+    if (!success) {
+        self->num_batches_failed += 1;
+    }
+
+    DECREF(batch_runner);
+    return success;
+}
+
+bool
+TestSuiteRunner_finish(TestSuiteRunner *self) {
+    TestFormatter_Summary(self->formatter, self);
+
+    return self->num_batches != 0 && self->num_batches_failed == 0;
+}
+
+uint32_t
+TestSuiteRunner_get_num_tests(TestSuiteRunner *self) {
+    return self->num_tests;
+}
+
+uint32_t
+TestSuiteRunner_get_num_tests_failed(TestSuiteRunner *self) {
+    return self->num_tests_failed;
+}
+
+uint32_t
+TestSuiteRunner_get_num_batches(TestSuiteRunner *self) {
+    return self->num_batches;
+}
+
+uint32_t
+TestSuiteRunner_get_num_batches_failed(TestSuiteRunner *self) {
+    return self->num_batches_failed;
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestSuiteRunner.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestSuiteRunner.cfh b/core/Clownfish/TestHarness/TestSuiteRunner.cfh
new file mode 100644
index 0000000..e9202f1
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestSuiteRunner.cfh
@@ -0,0 +1,76 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Clownfish;
+
+/** Run multiple test batches and collect statistics.
+ */
+class Clownfish::TestHarness::TestSuiteRunner inherits Clownfish::Obj {
+    TestFormatter *formatter;
+    uint32_t       num_tests;
+    uint32_t       num_tests_failed;
+    uint32_t       num_batches;
+    uint32_t       num_batches_failed;
+
+    inert incremented TestSuiteRunner*
+    new(TestFormatter *formatter);
+
+    /**
+     * @param formatter The test formatter to format the test output.
+     */
+    inert TestSuiteRunner*
+    init(TestSuiteRunner *self, TestFormatter *formatter);
+
+    public void
+    Destroy(TestSuiteRunner *self);
+
+    /** Run a test batch and collect statistics.
+     *
+     * @param batch The test batch.
+     * @return true if the test batch passed.
+     */
+    bool
+    Run_Batch(TestSuiteRunner *self, TestBatch *batch);
+
+    /** Print a summary after running all test batches.
+     *
+     * @return true if any tests were run and all test batches passed.
+     */
+    bool
+    Finish(TestSuiteRunner *self);
+
+    /** Return the number of tests run.
+     */
+    uint32_t
+    Get_Num_Tests(TestSuiteRunner *self);
+
+    /** Return the number of failed tests.
+     */
+    uint32_t
+    Get_Num_Tests_Failed(TestSuiteRunner *self);
+
+    /** Return the number of test batches run.
+     */
+    uint32_t
+    Get_Num_Batches(TestSuiteRunner *self);
+
+    /** Return the number of failed test batches.
+     */
+    uint32_t
+    Get_Num_Batches_Failed(TestSuiteRunner *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test.c b/core/Lucy/Test.c
index c131931..5923e98 100644
--- a/core/Lucy/Test.c
+++ b/core/Lucy/Test.c
@@ -14,15 +14,14 @@
  * limitations under the License.
  */
 
-#include <stdio.h>
-
+#define CFISH_USE_SHORT_NAMES
 #define TESTLUCY_USE_SHORT_NAMES
-#include "Lucy/Util/ToolSet.h"
 
 #include "Lucy/Test.h"
+
 #include "Clownfish/TestHarness/TestBatch.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
-#include "Clownfish/TestHarness/TestRunner.h"
+#include "Clownfish/TestHarness/TestSuite.h"
+
 #include "Lucy/Test/Analysis/TestAnalyzer.h"
 #include "Lucy/Test/Analysis/TestCaseFolder.h"
 #include "Lucy/Test/Analysis/TestNormalizer.h"
@@ -82,124 +81,71 @@
 #include "Lucy/Test/Util/TestMemoryPool.h"
 #include "Lucy/Test/Util/TestPriorityQueue.h"
 
-static void
-S_unbuffer_stdout();
-
-static VArray*
-S_all_test_batches(TestFormatter *formatter) {
-    VArray *batches = VA_new(0);
-
-    VA_Push(batches, (Obj*)TestPriQ_new(formatter));
-    VA_Push(batches, (Obj*)TestBitVector_new(formatter));
-    VA_Push(batches, (Obj*)TestMemPool_new(formatter));
-    VA_Push(batches, (Obj*)TestIxFileNames_new(formatter));
-    VA_Push(batches, (Obj*)TestJson_new(formatter));
-    VA_Push(batches, (Obj*)TestI32Arr_new(formatter));
-    VA_Push(batches, (Obj*)TestRAMFH_new(formatter));
-    VA_Push(batches, (Obj*)TestFSFH_new(formatter));
-    VA_Push(batches, (Obj*)TestInStream_new(formatter));
-    VA_Push(batches, (Obj*)TestFH_new(formatter));
-    VA_Push(batches, (Obj*)TestIOPrimitives_new(formatter));
-    VA_Push(batches, (Obj*)TestIOChunks_new(formatter));
-    VA_Push(batches, (Obj*)TestRAMDH_new(formatter));
-    VA_Push(batches, (Obj*)TestFSDH_new(formatter));
-    VA_Push(batches, (Obj*)TestFSFolder_new(formatter));
-    VA_Push(batches, (Obj*)TestRAMFolder_new(formatter));
-    VA_Push(batches, (Obj*)TestFolder_new(formatter));
-    VA_Push(batches, (Obj*)TestIxManager_new(formatter));
-    VA_Push(batches, (Obj*)TestCFWriter_new(formatter));
-    VA_Push(batches, (Obj*)TestCFReader_new(formatter));
-    VA_Push(batches, (Obj*)TestAnalyzer_new(formatter));
-    VA_Push(batches, (Obj*)TestPolyAnalyzer_new(formatter));
-    VA_Push(batches, (Obj*)TestCaseFolder_new(formatter));
-    VA_Push(batches, (Obj*)TestRegexTokenizer_new(formatter));
-    VA_Push(batches, (Obj*)TestSnowStop_new(formatter));
-    VA_Push(batches, (Obj*)TestSnowStemmer_new(formatter));
-    VA_Push(batches, (Obj*)TestNormalizer_new(formatter));
-    VA_Push(batches, (Obj*)TestStandardTokenizer_new(formatter));
-    VA_Push(batches, (Obj*)TestSnapshot_new(formatter));
-    VA_Push(batches, (Obj*)TestTermInfo_new(formatter));
-    VA_Push(batches, (Obj*)TestFieldMisc_new(formatter));
-    VA_Push(batches, (Obj*)TestBatchSchema_new(formatter));
-    VA_Push(batches, (Obj*)TestDocWriter_new(formatter));
-    VA_Push(batches, (Obj*)TestHLWriter_new(formatter));
-    VA_Push(batches, (Obj*)TestPListWriter_new(formatter));
-    VA_Push(batches, (Obj*)TestSegWriter_new(formatter));
-    VA_Push(batches, (Obj*)TestPolyReader_new(formatter));
-    VA_Push(batches, (Obj*)TestFullTextType_new(formatter));
-    VA_Push(batches, (Obj*)TestBlobType_new(formatter));
-    VA_Push(batches, (Obj*)TestNumericType_new(formatter));
-    VA_Push(batches, (Obj*)TestFType_new(formatter));
-    VA_Push(batches, (Obj*)TestSeg_new(formatter));
-    VA_Push(batches, (Obj*)TestHighlighter_new(formatter));
-    VA_Push(batches, (Obj*)TestSpan_new(formatter));
-    VA_Push(batches, (Obj*)TestHeatMap_new(formatter));
-    VA_Push(batches, (Obj*)TestTermQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestPhraseQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestSortSpec_new(formatter));
-    VA_Push(batches, (Obj*)TestRangeQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestANDQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestMatchAllQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestNOTQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestReqOptQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestLeafQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestNoMatchQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestSeriesMatcher_new(formatter));
-    VA_Push(batches, (Obj*)TestORQuery_new(formatter));
-    VA_Push(batches, (Obj*)TestQPLogic_new(formatter));
-    VA_Push(batches, (Obj*)TestQPSyntax_new(formatter));
-
-    return batches;
-}
-
-bool
-Test_run_batch(CharBuf *class_name, TestFormatter *formatter) {
-    S_unbuffer_stdout();
-
-    VArray   *batches = S_all_test_batches(formatter);
-    uint32_t  size    = VA_Get_Size(batches);
-
-    for (uint32_t i = 0; i < size; ++i) {
-        TestBatch *batch = (TestBatch*)VA_Fetch(batches, i);
-
-        if (CB_Equals(TestBatch_Get_Class_Name(batch), (Obj*)class_name)) {
-            bool result = TestBatch_Run(batch);
-            DECREF(batches);
-            return result;
-        }
-    }
-
-    DECREF(batches);
-    THROW(ERR, "Couldn't find test class '%o'", class_name);
-    UNREACHABLE_RETURN(bool);
-}
-
-bool
-Test_run_all_batches(TestFormatter *formatter) {
-    S_unbuffer_stdout();
-
-    TestRunner *runner  = TestRunner_new(formatter);
-    VArray     *batches = S_all_test_batches(formatter);
-    uint32_t    size    = VA_Get_Size(batches);
-
-    for (uint32_t i = 0; i < size; ++i) {
-        TestBatch *batch = (TestBatch*)VA_Fetch(batches, i);
-        TestRunner_Run_Batch(runner, batch);
-    }
-
-    bool result = TestRunner_Finish(runner);
-
-    DECREF(runner);
-    DECREF(batches);
-    return result;
-}
-
-static void
-S_unbuffer_stdout() {
-    int check_val = setvbuf(stdout, NULL, _IONBF, 0);
-    if (check_val != 0) {
-        fprintf(stderr, "Failed when trying to unbuffer stdout\n");
-    }
+TestSuite*
+Test_create_test_suite() {
+    TestSuite *suite = TestSuite_new();
+
+    TestSuite_Add_Batch(suite, (TestBatch*)TestPriQ_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestBitVector_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestMemPool_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestIxFileNames_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestJson_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestI32Arr_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestRAMFH_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestFSFH_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestInStream_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestFH_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestIOPrimitives_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestIOChunks_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestRAMDH_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestFSDH_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestFSFolder_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestRAMFolder_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestFolder_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestIxManager_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestCFWriter_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestCFReader_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestAnalyzer_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestPolyAnalyzer_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestCaseFolder_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestRegexTokenizer_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestSnowStop_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestSnowStemmer_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestNormalizer_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestStandardTokenizer_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestSnapshot_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestTermInfo_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestFieldMisc_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestBatchSchema_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestDocWriter_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestHLWriter_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestPListWriter_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestSegWriter_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestPolyReader_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestFullTextType_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestBlobType_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestNumericType_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestFType_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestSeg_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestHighlighter_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestSpan_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestHeatMap_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestTermQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestPhraseQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestSortSpec_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestRangeQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestANDQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestMatchAllQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestNOTQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestReqOptQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestLeafQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestNoMatchQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestSeriesMatcher_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestORQuery_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestQPLogic_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestQPSyntax_new());
+
+    return suite;
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test.cfh b/core/Lucy/Test.cfh
index 4c215bb..3b39130 100644
--- a/core/Lucy/Test.cfh
+++ b/core/Lucy/Test.cfh
@@ -16,27 +16,11 @@
 
 parcel TestLucy;
 
-/** Testing framework.
+/** Lucy test suite.
  */
 inert class Lucy::Test {
-    inert bool
-    run_batch(CharBuf *class_name, TestFormatter *formatter);
-
-    inert bool
-    run_all_batches(TestFormatter *formatter);
+    inert incremented TestSuite*
+    create_test_suite();
 }
 
-__C__
-#ifdef LUCY_USE_SHORT_NAMES
-  #define TEST_TRUE                    cfish_TestBatch_test_true
-  #define TEST_FALSE                   cfish_TestBatch_test_false
-  #define TEST_INT_EQ                  cfish_TestBatch_test_int_equals
-  #define TEST_FLOAT_EQ                cfish_TestBatch_test_float_equals
-  #define TEST_STR_EQ                  cfish_TestBatch_test_string_equals
-  #define PASS                         cfish_TestBatch_pass
-  #define FAIL                         cfish_TestBatch_fail
-  #define SKIP                         cfish_TestBatch_skip
-#endif
-__END_C__
-
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestAnalyzer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestAnalyzer.c b/core/Lucy/Test/Analysis/TestAnalyzer.c
index 04e6fc7..f7dba1c 100644
--- a/core/Lucy/Test/Analysis/TestAnalyzer.c
+++ b/core/Lucy/Test/Analysis/TestAnalyzer.c
@@ -17,7 +17,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Analysis/TestAnalyzer.h"
@@ -25,14 +25,8 @@
 #include "Lucy/Analysis/Inversion.h"
 
 TestAnalyzer*
-TestAnalyzer_new(TestFormatter *formatter) {
-    TestAnalyzer *self = (TestAnalyzer*)VTable_Make_Obj(TESTANALYZER);
-    return TestAnalyzer_init(self, formatter);
-}
-
-TestAnalyzer*
-TestAnalyzer_init(TestAnalyzer *self, TestFormatter *formatter) {
-    return (TestAnalyzer*)TestBatch_init((TestBatch*)self, 3, formatter);
+TestAnalyzer_new() {
+    return (TestAnalyzer*)VTable_Make_Obj(TESTANALYZER);
 }
 
 DummyAnalyzer*
@@ -53,12 +47,12 @@ DummyAnalyzer_transform(DummyAnalyzer *self, Inversion *inversion) {
 }
 
 static void
-test_analysis(TestBatch *batch) {
+test_analysis(TestBatchRunner *runner) {
     DummyAnalyzer *analyzer = DummyAnalyzer_new();
     CharBuf *source = CB_newf("foo bar baz");
     VArray *wanted = VA_new(1);
     VA_Push(wanted, (Obj*)CB_newf("foo bar baz"));
-    TestUtils_test_analyzer(batch, (Analyzer*)analyzer, source, wanted,
+    TestUtils_test_analyzer(runner, (Analyzer*)analyzer, source, wanted,
                             "test basic analysis");
     DECREF(wanted);
     DECREF(source);
@@ -66,9 +60,9 @@ test_analysis(TestBatch *batch) {
 }
 
 void
-TestAnalyzer_run_tests(TestAnalyzer *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_analysis(batch);
+TestAnalyzer_run(TestAnalyzer *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 3);
+    test_analysis(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestAnalyzer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestAnalyzer.cfh b/core/Lucy/Test/Analysis/TestAnalyzer.cfh
index e9d67ea..661e391 100644
--- a/core/Lucy/Test/Analysis/TestAnalyzer.cfh
+++ b/core/Lucy/Test/Analysis/TestAnalyzer.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Analysis::TestAnalyzer
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestAnalyzer*
-    new(TestFormatter *formatter);
-
-    inert TestAnalyzer*
-    init(TestAnalyzer *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestAnalyzer *self);
+    Run(TestAnalyzer *self, TestBatchRunner *runner);
 }
 
 class Lucy::Test::Analysis::DummyAnalyzer inherits Lucy::Analysis::Analyzer {

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestCaseFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestCaseFolder.c b/core/Lucy/Test/Analysis/TestCaseFolder.c
index 1c8670b..9ee90fe 100644
--- a/core/Lucy/Test/Analysis/TestCaseFolder.c
+++ b/core/Lucy/Test/Analysis/TestCaseFolder.c
@@ -18,34 +18,28 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Analysis/TestCaseFolder.h"
 #include "Lucy/Analysis/CaseFolder.h"
 
 TestCaseFolder*
-TestCaseFolder_new(TestFormatter *formatter) {
-    TestCaseFolder *self = (TestCaseFolder*)VTable_Make_Obj(TESTCASEFOLDER);
-    return TestCaseFolder_init(self, formatter);
-}
-
-TestCaseFolder*
-TestCaseFolder_init(TestCaseFolder *self, TestFormatter *formatter) {
-    return (TestCaseFolder*)TestBatch_init((TestBatch*)self, 6, formatter);
+TestCaseFolder_new() {
+    return (TestCaseFolder*)VTable_Make_Obj(TESTCASEFOLDER);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     CaseFolder *case_folder = CaseFolder_new();
     CaseFolder *other       = CaseFolder_new();
     Obj        *dump        = (Obj*)CaseFolder_Dump(case_folder);
     CaseFolder *clone       = (CaseFolder*)CaseFolder_Load(other, dump);
 
-    TEST_TRUE(batch, CaseFolder_Equals(case_folder, (Obj*)other), "Equals");
-    TEST_FALSE(batch, CaseFolder_Equals(case_folder, (Obj*)CFISH_TRUE),
+    TEST_TRUE(runner, CaseFolder_Equals(case_folder, (Obj*)other), "Equals");
+    TEST_FALSE(runner, CaseFolder_Equals(case_folder, (Obj*)CFISH_TRUE),
                "Not Equals");
-    TEST_TRUE(batch, CaseFolder_Equals(case_folder, (Obj*)clone),
+    TEST_TRUE(runner, CaseFolder_Equals(case_folder, (Obj*)clone),
               "Dump => Load round trip");
 
     DECREF(case_folder);
@@ -55,12 +49,12 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 static void
-test_analysis(TestBatch *batch) {
+test_analysis(TestBatchRunner *runner) {
     CaseFolder *case_folder = CaseFolder_new();
     CharBuf *source = CB_newf("caPiTal ofFensE");
     VArray *wanted = VA_new(1);
     VA_Push(wanted, (Obj*)CB_newf("capital offense"));
-    TestUtils_test_analyzer(batch, (Analyzer*)case_folder, source, wanted,
+    TestUtils_test_analyzer(runner, (Analyzer*)case_folder, source, wanted,
                             "lowercase plain text");
     DECREF(wanted);
     DECREF(source);
@@ -68,10 +62,10 @@ test_analysis(TestBatch *batch) {
 }
 
 void
-TestCaseFolder_run_tests(TestCaseFolder *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
-    test_analysis(batch);
+TestCaseFolder_run(TestCaseFolder *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
+    test_Dump_Load_and_Equals(runner);
+    test_analysis(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestCaseFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestCaseFolder.cfh b/core/Lucy/Test/Analysis/TestCaseFolder.cfh
index 2ff9067..6138139 100644
--- a/core/Lucy/Test/Analysis/TestCaseFolder.cfh
+++ b/core/Lucy/Test/Analysis/TestCaseFolder.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Analysis::TestCaseFolder
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestCaseFolder*
-    new(TestFormatter *formatter);
-
-    inert TestCaseFolder*
-    init(TestCaseFolder *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestCaseFolder *self);
+    Run(TestCaseFolder *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestNormalizer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestNormalizer.c b/core/Lucy/Test/Analysis/TestNormalizer.c
index 40d26e3..8824b01 100644
--- a/core/Lucy/Test/Analysis/TestNormalizer.c
+++ b/core/Lucy/Test/Analysis/TestNormalizer.c
@@ -19,7 +19,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestNormalizer.h"
 #include "Lucy/Analysis/Normalizer.h"
@@ -27,18 +27,12 @@
 #include "Lucy/Util/Json.h"
 
 TestNormalizer*
-TestNormalizer_new(TestFormatter *formatter) {
-    TestNormalizer *self = (TestNormalizer*)VTable_Make_Obj(TESTNORMALIZER);
-    return TestNormalizer_init(self, formatter);
-}
-
-TestNormalizer*
-TestNormalizer_init(TestNormalizer *self, TestFormatter *formatter) {
-    return (TestNormalizer*)TestBatch_init((TestBatch*)self, 20, formatter);
+TestNormalizer_new() {
+    return (TestNormalizer*)VTable_Make_Obj(TESTNORMALIZER);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     Normalizer *normalizer[4];
 
     CharBuf *NFC  = (CharBuf*)ZCB_WRAP_STR("NFC",  3);
@@ -49,13 +43,13 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     normalizer[2] = Normalizer_new(NFKC, false, false);
     normalizer[3] = Normalizer_new(NFKC, true,  true);
 
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                Normalizer_Equals(normalizer[0], (Obj*)normalizer[1]),
                "Equals() false with different normalization form");
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                Normalizer_Equals(normalizer[0], (Obj*)normalizer[2]),
                "Equals() false with different case_fold flag");
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                Normalizer_Equals(normalizer[0], (Obj*)normalizer[3]),
                "Equals() false with different strip_accents flag");
 
@@ -63,7 +57,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
         Obj *dump = (Obj*)Normalizer_Dump(normalizer[i]);
         Normalizer *clone = (Normalizer*)Normalizer_Load(normalizer[i], dump);
 
-        TEST_TRUE(batch,
+        TEST_TRUE(runner,
                   Normalizer_Equals(normalizer[i], (Obj*)clone),
                   "Dump => Load round trip");
 
@@ -74,7 +68,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 static void
-test_normalization(TestBatch *batch) {
+test_normalization(TestBatchRunner *runner) {
     CharBuf  *path           = CB_newf("modules");
     FSFolder *modules_folder = FSFolder_new(path);
     if (!FSFolder_Check(modules_folder)) {
@@ -104,7 +98,7 @@ test_normalization(TestBatch *batch) {
             CharBuf *word = (CharBuf*)VA_Fetch(words, j);
             VArray  *got  = Normalizer_Split(normalizer, word);
             CharBuf *norm = (CharBuf*)VA_Fetch(got, 0);
-            TEST_TRUE(batch,
+            TEST_TRUE(runner,
                       norm
                       && CB_Is_A(norm, CHARBUF)
                       && CB_Equals(norm, VA_Fetch(norms, j)),
@@ -122,10 +116,10 @@ test_normalization(TestBatch *batch) {
 }
 
 void
-TestNormalizer_run_tests(TestNormalizer *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
-    test_normalization(batch);
+TestNormalizer_run(TestNormalizer *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 20);
+    test_Dump_Load_and_Equals(runner);
+    test_normalization(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestNormalizer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestNormalizer.cfh b/core/Lucy/Test/Analysis/TestNormalizer.cfh
index ac5567f..0200838 100644
--- a/core/Lucy/Test/Analysis/TestNormalizer.cfh
+++ b/core/Lucy/Test/Analysis/TestNormalizer.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Analysis::TestNormalizer
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNormalizer*
-    new(TestFormatter *formatter);
-
-    inert TestNormalizer*
-    init(TestNormalizer *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestNormalizer *self);
+    Run(TestNormalizer *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestPolyAnalyzer.c b/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
index cee8df1..dc88aa1 100644
--- a/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
+++ b/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test/Analysis/TestPolyAnalyzer.h"
@@ -30,23 +30,16 @@
 #include "Lucy/Analysis/StandardTokenizer.h"
 
 TestPolyAnalyzer*
-TestPolyAnalyzer_new(TestFormatter *formatter) {
-    TestPolyAnalyzer *self
-        = (TestPolyAnalyzer*)VTable_Make_Obj(TESTPOLYANALYZER);
-    return TestPolyAnalyzer_init(self, formatter);
-}
-
-TestPolyAnalyzer*
-TestPolyAnalyzer_init(TestPolyAnalyzer *self, TestFormatter *formatter) {
-    return (TestPolyAnalyzer*)TestBatch_init((TestBatch*)self, 19, formatter);
+TestPolyAnalyzer_new() {
+    return (TestPolyAnalyzer*)VTable_Make_Obj(TESTPOLYANALYZER);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     if (!RegexTokenizer_is_available()) {
-        SKIP(batch, "RegexTokenizer not available");
-        SKIP(batch, "RegexTokenizer not available");
-        SKIP(batch, "RegexTokenizer not available");
+        SKIP(runner, "RegexTokenizer not available");
+        SKIP(runner, "RegexTokenizer not available");
+        SKIP(runner, "RegexTokenizer not available");
         return;
     }
 
@@ -60,11 +53,11 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     PolyAnalyzer *other_clone
         = (PolyAnalyzer*)PolyAnalyzer_Load(other, other_dump);
 
-    TEST_FALSE(batch, PolyAnalyzer_Equals(analyzer, (Obj*)other),
+    TEST_FALSE(runner, PolyAnalyzer_Equals(analyzer, (Obj*)other),
                "Equals() false with different language");
-    TEST_TRUE(batch, PolyAnalyzer_Equals(analyzer, (Obj*)clone),
+    TEST_TRUE(runner, PolyAnalyzer_Equals(analyzer, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_TRUE(batch, PolyAnalyzer_Equals(other, (Obj*)other_clone),
+    TEST_TRUE(runner, PolyAnalyzer_Equals(other, (Obj*)other_clone),
               "Dump => Load round trip");
 
     DECREF(analyzer);
@@ -76,7 +69,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 static void
-test_analysis(TestBatch *batch) {
+test_analysis(TestBatchRunner *runner) {
     CharBuf            *EN          = (CharBuf*)ZCB_WRAP_STR("en", 2);
     CharBuf            *source_text = CB_newf("Eats, shoots and leaves.");
     Normalizer         *normalizer  = Normalizer_new(NULL, true, false);
@@ -89,7 +82,7 @@ test_analysis(TestBatch *batch) {
         PolyAnalyzer *polyanalyzer = PolyAnalyzer_new(NULL, analyzers);
         VArray       *expected     = VA_new(1);
         VA_Push(expected, INCREF(source_text));
-        TestUtils_test_analyzer(batch, (Analyzer*)polyanalyzer, source_text,
+        TestUtils_test_analyzer(runner, (Analyzer*)polyanalyzer, source_text,
                                 expected, "No sub analyzers");
         DECREF(expected);
         DECREF(polyanalyzer);
@@ -102,7 +95,7 @@ test_analysis(TestBatch *batch) {
         PolyAnalyzer *polyanalyzer = PolyAnalyzer_new(NULL, analyzers);
         VArray       *expected     = VA_new(1);
         VA_Push(expected, (Obj*)CB_newf("eats, shoots and leaves."));
-        TestUtils_test_analyzer(batch, (Analyzer*)polyanalyzer, source_text,
+        TestUtils_test_analyzer(runner, (Analyzer*)polyanalyzer, source_text,
                                 expected, "With Normalizer");
         DECREF(expected);
         DECREF(polyanalyzer);
@@ -119,7 +112,7 @@ test_analysis(TestBatch *batch) {
         VA_Push(expected, (Obj*)CB_newf("shoots"));
         VA_Push(expected, (Obj*)CB_newf("and"));
         VA_Push(expected, (Obj*)CB_newf("leaves"));
-        TestUtils_test_analyzer(batch, (Analyzer*)polyanalyzer, source_text,
+        TestUtils_test_analyzer(runner, (Analyzer*)polyanalyzer, source_text,
                                 expected, "With StandardTokenizer");
         DECREF(expected);
         DECREF(polyanalyzer);
@@ -136,7 +129,7 @@ test_analysis(TestBatch *batch) {
         VA_Push(expected, (Obj*)CB_newf("eats"));
         VA_Push(expected, (Obj*)CB_newf("shoots"));
         VA_Push(expected, (Obj*)CB_newf("leaves"));
-        TestUtils_test_analyzer(batch, (Analyzer*)polyanalyzer, source_text,
+        TestUtils_test_analyzer(runner, (Analyzer*)polyanalyzer, source_text,
                                 expected, "With SnowballStopFilter");
         DECREF(expected);
         DECREF(polyanalyzer);
@@ -154,7 +147,7 @@ test_analysis(TestBatch *batch) {
         VA_Push(expected, (Obj*)CB_newf("eat"));
         VA_Push(expected, (Obj*)CB_newf("shoot"));
         VA_Push(expected, (Obj*)CB_newf("leav"));
-        TestUtils_test_analyzer(batch, (Analyzer*)polyanalyzer, source_text,
+        TestUtils_test_analyzer(runner, (Analyzer*)polyanalyzer, source_text,
                                 expected, "With SnowballStemmer");
         DECREF(expected);
         DECREF(polyanalyzer);
@@ -169,20 +162,20 @@ test_analysis(TestBatch *batch) {
 }
 
 static void
-test_Get_Analyzers(TestBatch *batch) {
+test_Get_Analyzers(TestBatchRunner *runner) {
     VArray *analyzers = VA_new(0);
     PolyAnalyzer *analyzer = PolyAnalyzer_new(NULL, analyzers);
-    TEST_TRUE(batch, PolyAnalyzer_Get_Analyzers(analyzer) == analyzers,
+    TEST_TRUE(runner, PolyAnalyzer_Get_Analyzers(analyzer) == analyzers,
               "Get_Analyzers()");
     DECREF(analyzer);
     DECREF(analyzers);
 }
 
 void
-TestPolyAnalyzer_run_tests(TestPolyAnalyzer *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
-    test_analysis(batch);
-    test_Get_Analyzers(batch);
+TestPolyAnalyzer_run(TestPolyAnalyzer *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 19);
+    test_Dump_Load_and_Equals(runner);
+    test_analysis(runner);
+    test_Get_Analyzers(runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh b/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
index 7d4d2fc..cd50a76 100644
--- a/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
+++ b/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Analysis::TestPolyAnalyzer
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPolyAnalyzer*
-    new(TestFormatter *formatter);
-
-    inert TestPolyAnalyzer*
-    init(TestPolyAnalyzer *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestPolyAnalyzer *self);
+    Run(TestPolyAnalyzer *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestRegexTokenizer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestRegexTokenizer.c b/core/Lucy/Test/Analysis/TestRegexTokenizer.c
index cf9bb72..054068a 100644
--- a/core/Lucy/Test/Analysis/TestRegexTokenizer.c
+++ b/core/Lucy/Test/Analysis/TestRegexTokenizer.c
@@ -18,30 +18,23 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestRegexTokenizer.h"
 #include "Lucy/Analysis/RegexTokenizer.h"
 
 
 TestRegexTokenizer*
-TestRegexTokenizer_new(TestFormatter *formatter) {
-    TestRegexTokenizer *self
-        = (TestRegexTokenizer*)VTable_Make_Obj(TESTREGEXTOKENIZER);
-    return TestRegexTokenizer_init(self, formatter);
-}
-
-TestRegexTokenizer*
-TestRegexTokenizer_init(TestRegexTokenizer *self, TestFormatter *formatter) {
-    return (TestRegexTokenizer*)TestBatch_init((TestBatch*)self, 3, formatter);
+TestRegexTokenizer_new() {
+    return (TestRegexTokenizer*)VTable_Make_Obj(TESTREGEXTOKENIZER);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     if (!RegexTokenizer_is_available()) {
-        SKIP(batch, "RegexTokenizer not available");
-        SKIP(batch, "RegexTokenizer not available");
-        SKIP(batch, "RegexTokenizer not available");
+        SKIP(runner, "RegexTokenizer not available");
+        SKIP(runner, "RegexTokenizer not available");
+        SKIP(runner, "RegexTokenizer not available");
         return;
     }
 
@@ -58,13 +51,13 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     RegexTokenizer *whitespace_clone
         = RegexTokenizer_Load(whitespace_tokenizer, whitespace_dump);
 
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                RegexTokenizer_Equals(word_char_tokenizer, (Obj*)whitespace_tokenizer),
                "Equals() false with different pattern");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               RegexTokenizer_Equals(word_char_tokenizer, (Obj*)word_char_clone),
               "Dump => Load round trip");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               RegexTokenizer_Equals(whitespace_tokenizer, (Obj*)whitespace_clone),
               "Dump => Load round trip");
 
@@ -77,9 +70,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestRegexTokenizer_run_tests(TestRegexTokenizer *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestRegexTokenizer_run(TestRegexTokenizer *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 3);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh b/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
index bb0f352..00e3a60 100644
--- a/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
+++ b/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Analysis::TestRegexTokenizer
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRegexTokenizer*
-    new(TestFormatter *formatter);
-
-    inert TestRegexTokenizer*
-    init(TestRegexTokenizer *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestRegexTokenizer *self);
+    Run(TestRegexTokenizer *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestSnowballStemmer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStemmer.c b/core/Lucy/Test/Analysis/TestSnowballStemmer.c
index 36a1879..914f453 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStemmer.c
+++ b/core/Lucy/Test/Analysis/TestSnowballStemmer.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestSnowballStemmer.h"
 #include "Lucy/Analysis/SnowballStemmer.h"
@@ -26,18 +26,12 @@
 #include "Lucy/Util/Json.h"
 
 TestSnowballStemmer*
-TestSnowStemmer_new(TestFormatter *formatter) {
-    TestSnowballStemmer *self = (TestSnowballStemmer*)VTable_Make_Obj(TESTSNOWBALLSTEMMER);
-    return TestSnowStemmer_init(self, formatter);
-}
-
-TestSnowballStemmer*
-TestSnowStemmer_init(TestSnowballStemmer *self, TestFormatter *formatter) {
-    return (TestSnowballStemmer*)TestBatch_init((TestBatch*)self, 153, formatter);
+TestSnowStemmer_new() {
+    return (TestSnowballStemmer*)VTable_Make_Obj(TESTSNOWBALLSTEMMER);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     CharBuf *EN = (CharBuf*)ZCB_WRAP_STR("en", 2);
     CharBuf *ES = (CharBuf*)ZCB_WRAP_STR("es", 2);
     SnowballStemmer *stemmer = SnowStemmer_new(EN);
@@ -47,13 +41,13 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     SnowballStemmer *clone       = (SnowballStemmer*)SnowStemmer_Load(other, dump);
     SnowballStemmer *other_clone = (SnowballStemmer*)SnowStemmer_Load(other, other_dump);
 
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                SnowStemmer_Equals(stemmer, (Obj*)other),
                "Equals() false with different language");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               SnowStemmer_Equals(stemmer, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               SnowStemmer_Equals(other, (Obj*)other_clone),
               "Dump => Load round trip");
 
@@ -66,7 +60,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 static void
-test_stemming(TestBatch *batch) {
+test_stemming(TestBatchRunner *runner) {
     CharBuf  *path           = CB_newf("modules");
     FSFolder *modules_folder = FSFolder_new(path);
     if (!FSFolder_Check(modules_folder)) {
@@ -92,7 +86,7 @@ test_stemming(TestBatch *batch) {
             CharBuf *word  = (CharBuf*)VA_Fetch(words, i);
             VArray  *got   = SnowStemmer_Split(stemmer, word);
             CharBuf *stem  = (CharBuf*)VA_Fetch(got, 0);
-            TEST_TRUE(batch,
+            TEST_TRUE(runner,
                       stem
                       && CB_Is_A(stem, CHARBUF)
                       && CB_Equals(stem, VA_Fetch(stems, i)),
@@ -109,10 +103,10 @@ test_stemming(TestBatch *batch) {
 }
 
 void
-TestSnowStemmer_run_tests(TestSnowballStemmer *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
-    test_stemming(batch);
+TestSnowStemmer_run(TestSnowballStemmer *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 153);
+    test_Dump_Load_and_Equals(runner);
+    test_stemming(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh b/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
index 8a651ee..6260b13 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
+++ b/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Analysis::TestSnowballStemmer cnick TestSnowStemmer
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSnowballStemmer*
-    new(TestFormatter *formatter);
-
-    inert TestSnowballStemmer*
-    init(TestSnowballStemmer *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSnowballStemmer *self);
+    Run(TestSnowballStemmer *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStopFilter.c b/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
index 217464a..5a3bd9e 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
+++ b/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
@@ -18,20 +18,14 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestSnowballStopFilter.h"
 #include "Lucy/Analysis/SnowballStopFilter.h"
 
 TestSnowballStopFilter*
-TestSnowStop_new(TestFormatter *formatter) {
-    TestSnowballStopFilter *self = (TestSnowballStopFilter*)VTable_Make_Obj(TESTSNOWBALLSTOPFILTER);
-    return TestSnowStop_init(self, formatter);
-}
-
-TestSnowballStopFilter*
-TestSnowStop_init(TestSnowballStopFilter *self, TestFormatter *formatter) {
-    return (TestSnowballStopFilter*)TestBatch_init((TestBatch*)self, 3, formatter);
+TestSnowStop_new() {
+    return (TestSnowballStopFilter*)VTable_Make_Obj(TESTSNOWBALLSTOPFILTER);
 }
 
 static SnowballStopFilter*
@@ -54,7 +48,7 @@ S_make_stopfilter(void *unused, ...) {
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     SnowballStopFilter *stopfilter =
         S_make_stopfilter(NULL, "foo", "bar", "baz", NULL);
     SnowballStopFilter *other =
@@ -64,13 +58,13 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
     SnowballStopFilter *clone       = (SnowballStopFilter*)SnowStop_Load(other, dump);
     SnowballStopFilter *other_clone = (SnowballStopFilter*)SnowStop_Load(other, other_dump);
 
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                SnowStop_Equals(stopfilter, (Obj*)other),
                "Equals() false with different stoplist");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               SnowStop_Equals(stopfilter, (Obj*)clone),
               "Dump => Load round trip");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               SnowStop_Equals(other, (Obj*)other_clone),
               "Dump => Load round trip");
 
@@ -83,9 +77,9 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 void
-TestSnowStop_run_tests(TestSnowballStopFilter *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
+TestSnowStop_run(TestSnowballStopFilter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 3);
+    test_Dump_Load_and_Equals(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh b/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
index 33140a5..63494f2 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
+++ b/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Analysis::TestSnowballStopFilter cnick TestSnowStop
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestSnowballStopFilter*
-    new(TestFormatter *formatter);
-
-    inert TestSnowballStopFilter*
-    init(TestSnowballStopFilter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestSnowballStopFilter *self);
+    Run(TestSnowballStopFilter *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestStandardTokenizer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestStandardTokenizer.c b/core/Lucy/Test/Analysis/TestStandardTokenizer.c
index 063e17c..2400368 100644
--- a/core/Lucy/Test/Analysis/TestStandardTokenizer.c
+++ b/core/Lucy/Test/Analysis/TestStandardTokenizer.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Analysis/TestStandardTokenizer.h"
 #include "Lucy/Analysis/StandardTokenizer.h"
@@ -26,27 +26,18 @@
 #include "Lucy/Util/Json.h"
 
 TestStandardTokenizer*
-TestStandardTokenizer_new(TestFormatter *formatter) {
-    TestStandardTokenizer *self
-        = (TestStandardTokenizer*)VTable_Make_Obj(TESTSTANDARDTOKENIZER);
-    return TestStandardTokenizer_init(self, formatter);
-}
-
-TestStandardTokenizer*
-TestStandardTokenizer_init(TestStandardTokenizer *self,
-                           TestFormatter *formatter) {
-    TestBatch_init((TestBatch*)self, 1084, formatter);
-    return self;
+TestStandardTokenizer_new() {
+    return (TestStandardTokenizer*)VTable_Make_Obj(TESTSTANDARDTOKENIZER);
 }
 
 static void
-test_Dump_Load_and_Equals(TestBatch *batch) {
+test_Dump_Load_and_Equals(TestBatchRunner *runner) {
     StandardTokenizer *tokenizer = StandardTokenizer_new();
     Obj *dump  = StandardTokenizer_Dump(tokenizer);
     StandardTokenizer *clone
         = (StandardTokenizer*)StandardTokenizer_Load(tokenizer, dump);
 
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               StandardTokenizer_Equals(tokenizer, (Obj*)clone),
               "Dump => Load round trip");
 
@@ -56,7 +47,7 @@ test_Dump_Load_and_Equals(TestBatch *batch) {
 }
 
 static void
-test_tokenizer(TestBatch *batch) {
+test_tokenizer(TestBatchRunner *runner) {
     StandardTokenizer *tokenizer = StandardTokenizer_new();
 
     ZombieCharBuf *word = ZCB_WRAP_STR(
@@ -71,31 +62,31 @@ test_tokenizer(TestBatch *batch) {
                               35);
     VArray *got = StandardTokenizer_Split(tokenizer, (CharBuf*)word);
     CharBuf *token = (CharBuf*)VA_Fetch(got, 0);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               token
               && CB_Is_A(token, CHARBUF)
               && CB_Equals_Str(token, "tha\xcc\x82t's", 8),
               "Token: %s", CB_Get_Ptr8(token));
     token = (CharBuf*)VA_Fetch(got, 1);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               token
               && CB_Is_A(token, CHARBUF)
               && CB_Equals_Str(token, "1,02\xC2\xADZ4.38", 11),
               "Token: %s", CB_Get_Ptr8(token));
     token = (CharBuf*)VA_Fetch(got, 2);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               token
               && CB_Is_A(token, CHARBUF)
               && CB_Equals_Str(token, "\xE0\xB8\x81\xC2\xAD\xC2\xAD", 7),
               "Token: %s", CB_Get_Ptr8(token));
     token = (CharBuf*)VA_Fetch(got, 3);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               token
               && CB_Is_A(token, CHARBUF)
               && CB_Equals_Str(token, "\xF0\xA0\x80\x80", 4),
               "Token: %s", CB_Get_Ptr8(token));
     token = (CharBuf*)VA_Fetch(got, 4);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               token
               && CB_Is_A(token, CHARBUF)
               && CB_Equals_Str(token, "a", 1),
@@ -121,7 +112,7 @@ test_tokenizer(TestBatch *batch) {
         CharBuf *text = (CharBuf*)Hash_Fetch_Str(test, "text", 4);
         VArray *wanted = (VArray*)Hash_Fetch_Str(test, "words", 5);
         VArray *got = StandardTokenizer_Split(tokenizer, text);
-        TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got), "UCD test #%d", i + 1);
+        TEST_TRUE(runner, VA_Equals(wanted, (Obj*)got), "UCD test #%d", i + 1);
         DECREF(got);
     }
 
@@ -133,10 +124,10 @@ test_tokenizer(TestBatch *batch) {
 }
 
 void
-TestStandardTokenizer_run_tests(TestStandardTokenizer *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Dump_Load_and_Equals(batch);
-    test_tokenizer(batch);
+TestStandardTokenizer_run(TestStandardTokenizer *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1084);
+    test_Dump_Load_and_Equals(runner);
+    test_tokenizer(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh b/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
index 257879d..8e3d942 100644
--- a/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
+++ b/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Analysis::TestStandardTokenizer
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestStandardTokenizer*
-    new(TestFormatter *formatter);
-
-    inert TestStandardTokenizer*
-    init(TestStandardTokenizer *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestStandardTokenizer *self);
+    Run(TestStandardTokenizer *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Highlight/TestHeatMap.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHeatMap.c b/core/Lucy/Test/Highlight/TestHeatMap.c
index 2f2da84..67b6397 100644
--- a/core/Lucy/Test/Highlight/TestHeatMap.c
+++ b/core/Lucy/Test/Highlight/TestHeatMap.c
@@ -17,7 +17,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Highlight/TestHeatMap.h"
 #include "Lucy/Highlight/HeatMap.h"
@@ -25,18 +25,12 @@
 #include "Lucy/Search/Span.h"
 
 TestHeatMap*
-TestHeatMap_new(TestFormatter *formatter) {
-    TestHeatMap *self = (TestHeatMap*)VTable_Make_Obj(TESTHEATMAP);
-    return TestHeatMap_init(self, formatter);
-}
-
-TestHeatMap*
-TestHeatMap_init(TestHeatMap *self, TestFormatter *formatter) {
-    return (TestHeatMap*)TestBatch_init((TestBatch*)self, 13, formatter);
+TestHeatMap_new() {
+    return (TestHeatMap*)VTable_Make_Obj(TESTHEATMAP);
 }
 
 static void
-test_calc_proximity_boost(TestBatch *batch) {
+test_calc_proximity_boost(TestBatchRunner *runner) {
     VArray  *spans    = VA_new(0);
     HeatMap *heat_map = HeatMap_new(spans, 133);
     Span    *span1    = Span_new(  0, 10, 1.0f);
@@ -50,10 +44,10 @@ test_calc_proximity_boost(TestBatch *batch) {
     float smaller_boost = HeatMap_Calc_Proximity_Boost(heat_map, span1, span4);
     float zero_boost    = HeatMap_Calc_Proximity_Boost(heat_map, span1, span5);
 
-    TEST_TRUE(batch, big_boost == eq_big_boost,
+    TEST_TRUE(runner, big_boost == eq_big_boost,
               "overlapping and abutting produce the same proximity boost");
-    TEST_TRUE(batch, big_boost > smaller_boost, "closer is better");
-    TEST_TRUE(batch, zero_boost == 0.0,
+    TEST_TRUE(runner, big_boost > smaller_boost, "closer is better");
+    TEST_TRUE(runner, zero_boost == 0.0,
               "distance outside of window yields no prox boost");
 
     DECREF(span1);
@@ -66,7 +60,7 @@ test_calc_proximity_boost(TestBatch *batch) {
 }
 
 static void
-test_flatten_spans(TestBatch *batch) {
+test_flatten_spans(TestBatchRunner *runner) {
     VArray  *spans    = VA_new(8);
     VArray  *wanted   = VA_new(8);
     HeatMap *heat_map = HeatMap_new(spans, 133);
@@ -79,12 +73,12 @@ test_flatten_spans(TestBatch *batch) {
     VA_Push(wanted, (Obj*)Span_new(10,  6, 1.0f));
     VA_Push(wanted, (Obj*)Span_new(16,  4, 3.0f));
     VA_Push(wanted, (Obj*)Span_new(20, 10, 2.0f));
-    TEST_TRUE(batch, VA_Equals(flattened, (Obj*)wanted),
+    TEST_TRUE(runner, VA_Equals(flattened, (Obj*)wanted),
               "flatten two overlapping spans");
     VA_Clear(wanted);
     boosts = HeatMap_Generate_Proximity_Boosts(heat_map, spans);
     VA_Push(wanted, (Obj*)Span_new(10, 20, 3.0f));
-    TEST_TRUE(batch, VA_Equals(boosts, (Obj*)wanted),
+    TEST_TRUE(runner, VA_Equals(boosts, (Obj*)wanted),
               "prox boosts for overlap");
     VA_Clear(wanted);
     VA_Clear(spans);
@@ -99,11 +93,11 @@ test_flatten_spans(TestBatch *batch) {
     VA_Push(wanted, (Obj*)Span_new(16,  4, 3.0f));
     VA_Push(wanted, (Obj*)Span_new(20, 10, 2.0f));
     VA_Push(wanted, (Obj*)Span_new(50,  1, 1.0f));
-    TEST_TRUE(batch, VA_Equals(flattened, (Obj*)wanted),
+    TEST_TRUE(runner, VA_Equals(flattened, (Obj*)wanted),
               "flatten two overlapping spans, leave hole, then third span");
     VA_Clear(wanted);
     boosts = HeatMap_Generate_Proximity_Boosts(heat_map, spans);
-    TEST_TRUE(batch, VA_Get_Size(boosts) == 2 + 1,
+    TEST_TRUE(runner, VA_Get_Size(boosts) == 2 + 1,
               "boosts generated for each unique pair, since all were in range");
     VA_Clear(spans);
     DECREF(boosts);
@@ -118,11 +112,11 @@ test_flatten_spans(TestBatch *batch) {
     VA_Push(wanted, (Obj*)Span_new(16,  2, 7.0f));
     VA_Push(wanted, (Obj*)Span_new(18,  2, 3.0f));
     VA_Push(wanted, (Obj*)Span_new(20, 10, 2.0f));
-    TEST_TRUE(batch, VA_Equals(flattened, (Obj*)wanted),
+    TEST_TRUE(runner, VA_Equals(flattened, (Obj*)wanted),
               "flatten three overlapping spans");
     VA_Clear(wanted);
     boosts = HeatMap_Generate_Proximity_Boosts(heat_map, spans);
-    TEST_TRUE(batch, VA_Get_Size(boosts) == 2 + 1,
+    TEST_TRUE(runner, VA_Get_Size(boosts) == 2 + 1,
               "boosts generated for each unique pair, since all were in range");
     VA_Clear(spans);
     DECREF(boosts);
@@ -137,11 +131,11 @@ test_flatten_spans(TestBatch *batch) {
     VA_Push(wanted, (Obj*)Span_new(16,  4,  7.0f));
     VA_Push(wanted, (Obj*)Span_new(20, 10,  6.0f));
     VA_Push(wanted, (Obj*)Span_new(30, 10, 10.0f));
-    TEST_TRUE(batch, VA_Equals(flattened, (Obj*)wanted),
+    TEST_TRUE(runner, VA_Equals(flattened, (Obj*)wanted),
               "flatten 4 spans, middle two have identical range");
     VA_Clear(wanted);
     boosts = HeatMap_Generate_Proximity_Boosts(heat_map, spans);
-    TEST_TRUE(batch, VA_Get_Size(boosts) == 3 + 2 + 1,
+    TEST_TRUE(runner, VA_Get_Size(boosts) == 3 + 2 + 1,
               "boosts generated for each unique pair, since all were in range");
     VA_Clear(spans);
     DECREF(boosts);
@@ -156,11 +150,11 @@ test_flatten_spans(TestBatch *batch) {
     VA_Push(wanted, (Obj*)Span_new( 16,  4,  7.0f));
     VA_Push(wanted, (Obj*)Span_new( 20, 10,  2.0f));
     VA_Push(wanted, (Obj*)Span_new(230, 10, 10.0f));
-    TEST_TRUE(batch, VA_Equals(flattened, (Obj*)wanted),
+    TEST_TRUE(runner, VA_Equals(flattened, (Obj*)wanted),
               "flatten 4 spans, middle two have identical starts but different ends");
     VA_Clear(wanted);
     boosts = HeatMap_Generate_Proximity_Boosts(heat_map, spans);
-    TEST_TRUE(batch, VA_Get_Size(boosts) == 2 + 1,
+    TEST_TRUE(runner, VA_Get_Size(boosts) == 2 + 1,
               "boosts not generated for out of range span");
     VA_Clear(spans);
     DECREF(boosts);
@@ -172,10 +166,10 @@ test_flatten_spans(TestBatch *batch) {
 }
 
 void
-TestHeatMap_run_tests(TestHeatMap *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_calc_proximity_boost(batch);
-    test_flatten_spans(batch);
+TestHeatMap_run(TestHeatMap *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 13);
+    test_calc_proximity_boost(runner);
+    test_flatten_spans(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Highlight/TestHeatMap.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHeatMap.cfh b/core/Lucy/Test/Highlight/TestHeatMap.cfh
index 2a4ed5a..d7ec574 100644
--- a/core/Lucy/Test/Highlight/TestHeatMap.cfh
+++ b/core/Lucy/Test/Highlight/TestHeatMap.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Highlight::TestHeatMap
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestHeatMap*
-    new(TestFormatter *formatter);
-
-    inert TestHeatMap*
-    init(TestHeatMap *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestHeatMap *self);
+    Run(TestHeatMap *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Highlight/TestHighlighter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHighlighter.c b/core/Lucy/Test/Highlight/TestHighlighter.c
index 808267b..fea4e62 100644
--- a/core/Lucy/Test/Highlight/TestHighlighter.c
+++ b/core/Lucy/Test/Highlight/TestHighlighter.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Highlight/TestHighlighter.h"
 #include "Lucy/Highlight/Highlighter.h"
@@ -53,18 +53,12 @@
 #define TEST_STRING_LEN 425
 
 TestHighlighter*
-TestHighlighter_new(TestFormatter *formatter) {
-    TestHighlighter *self = (TestHighlighter*)VTable_Make_Obj(TESTHIGHLIGHTER);
-    return TestHighlighter_init(self, formatter);
-}
-
-TestHighlighter*
-TestHighlighter_init(TestHighlighter *self, TestFormatter *formatter) {
-    return (TestHighlighter*)TestBatch_init((TestBatch*)self, 35, formatter);
+TestHighlighter_new() {
+    return (TestHighlighter*)VTable_Make_Obj(TESTHIGHLIGHTER);
 }
 
 static void
-test_Find_Best_Fragment(TestBatch *batch, Searcher *searcher, Obj *query) {
+test_Find_Best_Fragment(TestBatchRunner *runner, Searcher *searcher, Obj *query) {
     CharBuf *content = (CharBuf*)ZCB_WRAP_STR("content", 7);
     Highlighter *highlighter = Highlighter_new(searcher, query, content, 3);
     ViewCharBuf *target = (ViewCharBuf*)ZCB_BLANK();
@@ -76,19 +70,19 @@ test_Find_Best_Fragment(TestBatch *batch, Searcher *searcher, Obj *query) {
     CharBuf *field_val = (CharBuf *)ZCB_WRAP_STR("a " PHI " " PHI " b c", 11);
     int32_t top = Highlighter_Find_Best_Fragment(highlighter, field_val,
                                                  target, heat_map);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str((CharBuf *)target, PHI " " PHI " b", 7),
               "Find_Best_Fragment");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               top == 2,
               "correct offset returned by Find_Best_Fragment");
     field_val = (CharBuf *)ZCB_WRAP_STR("aa" PHI, 4);
     top = Highlighter_Find_Best_Fragment(highlighter, field_val,
                                          target, heat_map);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str((CharBuf *)target, "aa" PHI, 4),
               "Find_Best_Fragment returns whole field when field is short");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               top == 0,
               "correct offset");
     DECREF(heat_map);
@@ -100,10 +94,10 @@ test_Find_Best_Fragment(TestBatch *batch, Searcher *searcher, Obj *query) {
     field_val = (CharBuf *)ZCB_WRAP_STR("aaaab" PHI PHI, 9);
     top = Highlighter_Find_Best_Fragment(highlighter, field_val,
                                          target, heat_map);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str((CharBuf *)target, "b" PHI PHI, 5),
               "Find_Best_Fragment shifts left to deal with overrun");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               top == 4,
               "correct offset");
     DECREF(heat_map);
@@ -115,10 +109,10 @@ test_Find_Best_Fragment(TestBatch *batch, Searcher *searcher, Obj *query) {
     field_val = (CharBuf *)ZCB_WRAP_STR("a" PHI "bcde", 7);
     top = Highlighter_Find_Best_Fragment(highlighter, field_val,
                                          target, heat_map);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str((CharBuf *)target, "a" PHI "bcd", 6),
               "Find_Best_Fragment start at field beginning");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               top == 0,
               "correct offset");
     DECREF(heat_map);
@@ -127,7 +121,7 @@ test_Find_Best_Fragment(TestBatch *batch, Searcher *searcher, Obj *query) {
 }
 
 static void
-test_Raw_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
+test_Raw_Excerpt(TestBatchRunner *runner, Searcher *searcher, Obj *query) {
     CharBuf *content = (CharBuf*)ZCB_WRAP_STR("content", 7);
     Highlighter *highlighter = Highlighter_new(searcher, query, content, 6);
 
@@ -143,10 +137,10 @@ test_Raw_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     VA_Push(sentences, (Obj*)Span_new(6, 4, 0.0f));
     int32_t top = Highlighter_Raw_Excerpt(highlighter, field_val, fragment,
                                           raw_excerpt, 0, heat_map, sentences);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(raw_excerpt, "Ook.", 4),
               "Raw_Excerpt at top");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               top == 0,
               "top still 0");
     DECREF(sentences);
@@ -159,10 +153,10 @@ test_Raw_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     VA_Push(sentences, (Obj*)Span_new(12, 4, 0.0f));
     top = Highlighter_Raw_Excerpt(highlighter, field_val, fragment,
                                   raw_excerpt, 3, heat_map, sentences);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(raw_excerpt, "Urk.", 4),
               "Raw_Excerpt in middle, with 2 bounds");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               top == 6,
               "top in the middle modified by Raw_Excerpt");
     DECREF(sentences);
@@ -180,10 +174,10 @@ test_Raw_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     VA_Push(sentences, (Obj*)Span_new(0, 14, 0.0f));
     top = Highlighter_Raw_Excerpt(highlighter, field_val, fragment,
                                   raw_excerpt, 8, heat_map, sentences);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(raw_excerpt, ELLIPSIS " i.", 6),
               "Ellipsis at top");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               top == 10,
               "top correct when leading ellipsis inserted");
     DECREF(sentences);
@@ -201,10 +195,10 @@ test_Raw_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     VA_Push(sentences, (Obj*)Span_new(6, 11, 0.0f));
     top = Highlighter_Raw_Excerpt(highlighter, field_val, fragment,
                                   raw_excerpt, 4, heat_map, sentences);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(raw_excerpt, "Iz no" ELLIPSIS, 8),
               "Ellipsis at end");
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               top == 6,
               "top trimmed");
     DECREF(sentences);
@@ -224,7 +218,7 @@ test_Raw_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     DECREF(spans);
     top = Highlighter_Raw_Excerpt(highlighter, field_val, field_val,
                                   raw_excerpt, 0, heat_map, sentences);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(raw_excerpt, "abc/d" ELLIPSIS, 8),
               "Long word");
     DECREF(heat_map);
@@ -237,7 +231,7 @@ test_Raw_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     DECREF(spans);
     top = Highlighter_Raw_Excerpt(highlighter, field_val, field_val,
                                   raw_excerpt, 0, heat_map, sentences);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(raw_excerpt, ELLIPSIS " c/d" ELLIPSIS, 10),
               "Long word");
     DECREF(heat_map);
@@ -249,7 +243,7 @@ test_Raw_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
 }
 
 static void
-test_Highlight_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
+test_Highlight_Excerpt(TestBatchRunner *runner, Searcher *searcher, Obj *query) {
     CharBuf *content = (CharBuf*)ZCB_WRAP_STR("content", 7);
     Highlighter *highlighter = Highlighter_new(searcher, query, content, 3);
 
@@ -259,7 +253,7 @@ test_Highlight_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     CharBuf *highlighted = CB_new(0);
     Highlighter_Highlight_Excerpt(highlighter, spans, raw_excerpt,
                                   highlighted, 0);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(highlighted, "a <strong>b</strong> c", 22),
               "basic Highlight_Excerpt");
     DECREF(highlighted);
@@ -272,7 +266,7 @@ test_Highlight_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     highlighted = CB_new(0);
     Highlighter_Highlight_Excerpt(highlighter, spans, raw_excerpt,
                                   highlighted, 0);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(highlighted, "<strong>&#934;</strong>", 23),
               "don't surround spans off end of raw excerpt.");
     DECREF(highlighted);
@@ -284,7 +278,7 @@ test_Highlight_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     highlighted = CB_new(0);
     Highlighter_Highlight_Excerpt(highlighter, spans, raw_excerpt,
                                   highlighted, 1);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(highlighted,
                             "&#934; <strong>&#934;</strong> &#934;", 37),
               "Highlight_Excerpt pays attention to offset");
@@ -300,7 +294,7 @@ test_Highlight_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
     highlighted = CB_new(0);
     Highlighter_Highlight_Excerpt(highlighter, spans, raw_excerpt,
                                   highlighted, 0);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Equals_Str(highlighted,
                             "&#934; <strong>Oook. Urk. Ick.</strong> &#934;",
                             46),
@@ -312,14 +306,14 @@ test_Highlight_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query) {
 }
 
 static void
-test_Create_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query,
+test_Create_Excerpt(TestBatchRunner *runner, Searcher *searcher, Obj *query,
                     Hits *hits) {
     CharBuf *content = (CharBuf*)ZCB_WRAP_STR("content", 7);
     Highlighter *highlighter = Highlighter_new(searcher, query, content, 200);
 
     HitDoc *hit = Hits_Next(hits);
     CharBuf *excerpt = Highlighter_Create_Excerpt(highlighter, hit);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Find_Str(excerpt,
                           "<strong>&#934;</strong> a b c d <strong>x y z</strong>",
                           54) >= 0,
@@ -331,7 +325,7 @@ test_Create_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query,
     CharBuf *post_tag = (CharBuf*)ZCB_WRAP_STR("\x1B[0m", 4);
     Highlighter_Set_Post_Tag(highlighter, post_tag);
     excerpt = Highlighter_Create_Excerpt(highlighter, hit);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Find_Str(excerpt,
                           "\x1B[1m&#934;\x1B[0m a b c d \x1B[1mx y z\x1B[0m",
                           36) >= 0,
@@ -341,7 +335,7 @@ test_Create_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query,
 
     hit = Hits_Next(hits);
     excerpt = Highlighter_Create_Excerpt(highlighter, hit);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Find_Str(excerpt, "x", 1) >= 0,
               "excerpt field with partial hit doesn't cause highlighter freakout");
     DECREF(excerpt);
@@ -353,7 +347,7 @@ test_Create_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query,
     highlighter = Highlighter_new(searcher, query, content, 200);
     hit = Hits_Next(hits);
     excerpt = Highlighter_Create_Excerpt(highlighter, hit);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Find_Str(excerpt,
                           "<strong>b</strong> c d <strong>x y z</strong>",
                           45) >= 0,
@@ -368,7 +362,7 @@ test_Create_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query,
     highlighter = Highlighter_new(searcher, query, content, 200);
     hit = Hits_Next(hits);
     excerpt = Highlighter_Create_Excerpt(highlighter, hit);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Find_Str(excerpt, "&quot;", 6) >= 0,
               "HTML entity encoded properly");
     DECREF(excerpt);
@@ -381,7 +375,7 @@ test_Create_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query,
     highlighter = Highlighter_new(searcher, query, content, 200);
     hit = Hits_Next(hits);
     excerpt = Highlighter_Create_Excerpt(highlighter, hit);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Find_Str(excerpt, "&#934;", 6) == -1,
               "no ellipsis for short excerpt");
     DECREF(excerpt);
@@ -395,7 +389,7 @@ test_Create_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query,
     hit = Hits_Next(hits);
     highlighter = Highlighter_new(searcher, query, content, 200);
     excerpt = Highlighter_Create_Excerpt(highlighter, hit);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Find_Str(excerpt, "strong", 5) >= 0,
               "specify field highlights correct field...");
     DECREF(excerpt);
@@ -403,7 +397,7 @@ test_Create_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query,
     CharBuf *alt = (CharBuf*)ZCB_WRAP_STR("alt", 3);
     highlighter = Highlighter_new(searcher, query, alt, 200);
     excerpt = Highlighter_Create_Excerpt(highlighter, hit);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               CB_Find_Str(excerpt, "strong", 5) == -1,
               "... but not another field");
     DECREF(excerpt);
@@ -414,7 +408,7 @@ test_Create_Excerpt(TestBatch *batch, Searcher *searcher, Obj *query,
 }
 
 static void
-test_Find_Sentences(TestBatch *batch, Searcher *searcher, Obj *query) {
+test_Find_Sentences(TestBatchRunner *runner, Searcher *searcher, Obj *query) {
     CharBuf *content = (CharBuf*)ZCB_WRAP_STR("content", 7);
     Highlighter *highlighter = Highlighter_new(searcher, query, content, 200);
     CharBuf *text = (CharBuf*)ZCB_WRAP_STR(
@@ -429,14 +423,14 @@ test_Find_Sentences(TestBatch *batch, Searcher *searcher, Obj *query) {
     VArray *wanted = VA_new(2);
     VA_Push(wanted, (Obj*)Span_new(120, 19, 0.0f));
     VA_Push(wanted, (Obj*)Span_new(140, 19, 0.0f));
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               VA_Equals(got, (Obj*)wanted),
               "find_sentences with explicit args");
     DECREF(wanted);
     DECREF(got);
 
     got = Highlighter_Find_Sentences(highlighter, text, 101, 4);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               VA_Get_Size(got) == 0,
               "find_sentences with explicit args, finding nothing");
     DECREF(got);
@@ -446,7 +440,7 @@ test_Find_Sentences(TestBatch *batch, Searcher *searcher, Obj *query) {
     for (int i = 0; i < 15; ++i) {
         VA_Push(wanted, (Obj*)Span_new(i * 20, 19, 0.0f));
     }
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               VA_Equals(got, (Obj*)wanted),
               "find_sentences with default offset and length");
     DECREF(wanted);
@@ -456,7 +450,7 @@ test_Find_Sentences(TestBatch *batch, Searcher *searcher, Obj *query) {
     got = Highlighter_Find_Sentences(highlighter, text, 0, 0);
     wanted = VA_new(1);
     VA_Push(wanted, (Obj*)Span_new(1, 3, 0.0f));
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               VA_Equals(got, (Obj*)wanted),
               "Skip leading whitespace but get first sentence");
     DECREF(wanted);
@@ -466,7 +460,7 @@ test_Find_Sentences(TestBatch *batch, Searcher *searcher, Obj *query) {
 }
 
 static void
-test_highlighting(TestBatch *batch) {
+test_highlighting(TestBatchRunner *runner) {
     Schema *schema = Schema_new();
     StandardTokenizer *tokenizer = StandardTokenizer_new();
     FullTextType *plain_type = FullTextType_new((Analyzer*)tokenizer);
@@ -514,11 +508,11 @@ test_highlighting(TestBatch *batch) {
     Obj *query = (Obj*)ZCB_WRAP_STR("\"x y z\" AND " PHI, 14);
     Hits *hits = Searcher_Hits(searcher, query, 0, 10, NULL);
 
-    test_Find_Best_Fragment(batch, searcher, query);
-    test_Raw_Excerpt(batch, searcher, query);
-    test_Highlight_Excerpt(batch, searcher, query);
-    test_Create_Excerpt(batch, searcher, query, hits);
-    test_Find_Sentences(batch, searcher, query);
+    test_Find_Best_Fragment(runner, searcher, query);
+    test_Raw_Excerpt(runner, searcher, query);
+    test_Highlight_Excerpt(runner, searcher, query);
+    test_Create_Excerpt(runner, searcher, query, hits);
+    test_Find_Sentences(runner, searcher, query);
 
     DECREF(hits);
     DECREF(searcher);
@@ -527,7 +521,7 @@ test_highlighting(TestBatch *batch) {
 }
 
 static void
-test_hl_selection(TestBatch *batch) {
+test_hl_selection(TestBatchRunner *runner) {
     Schema *schema = Schema_new();
     StandardTokenizer *tokenizer = StandardTokenizer_new();
     FullTextType *plain_type = FullTextType_new((Analyzer*)tokenizer);
@@ -571,7 +565,7 @@ test_hl_selection(TestBatch *batch) {
     CharBuf *excerpt = Highlighter_Create_Excerpt(highlighter, hit);
     CharBuf *mmm = (CharBuf*)ZCB_WRAP_STR("MMM", 3);
     CharBuf *nnn = (CharBuf*)ZCB_WRAP_STR("NNN", 3);
-    TEST_TRUE(batch, CB_Find(excerpt, mmm) >= 0 || CB_Find(excerpt, nnn) >= 0,
+    TEST_TRUE(runner, CB_Find(excerpt, mmm) >= 0 || CB_Find(excerpt, nnn) >= 0,
               "Sentence boundary algo doesn't chop terms");
 
     DECREF(excerpt);
@@ -584,10 +578,10 @@ test_hl_selection(TestBatch *batch) {
 }
 
 void
-TestHighlighter_run_tests(TestHighlighter *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_highlighting(batch);
-    test_hl_selection(batch);
+TestHighlighter_run(TestHighlighter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 35);
+    test_highlighting(runner);
+    test_hl_selection(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Highlight/TestHighlighter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHighlighter.cfh b/core/Lucy/Test/Highlight/TestHighlighter.cfh
index 848836d..8cd625a 100644
--- a/core/Lucy/Test/Highlight/TestHighlighter.cfh
+++ b/core/Lucy/Test/Highlight/TestHighlighter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Highlight::TestHighlighter
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestHighlighter*
-    new(TestFormatter *formatter);
-
-    inert TestHighlighter*
-    init(TestHighlighter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestHighlighter *self);
+    Run(TestHighlighter *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestDocWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestDocWriter.c b/core/Lucy/Test/Index/TestDocWriter.c
index 879d830..64747ec 100644
--- a/core/Lucy/Test/Index/TestDocWriter.c
+++ b/core/Lucy/Test/Index/TestDocWriter.c
@@ -18,26 +18,20 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Index/TestDocWriter.h"
 #include "Lucy/Index/DocWriter.h"
 
 TestDocWriter*
-TestDocWriter_new(TestFormatter *formatter) {
-    TestDocWriter *self = (TestDocWriter*)VTable_Make_Obj(TESTDOCWRITER);
-    return TestDocWriter_init(self, formatter);
-}
-
-TestDocWriter*
-TestDocWriter_init(TestDocWriter *self, TestFormatter *formatter) {
-    return (TestDocWriter*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestDocWriter_new() {
+    return (TestDocWriter*)VTable_Make_Obj(TESTDOCWRITER);
 }
 
 void
-TestDocWriter_run_tests(TestDocWriter *self) {
-    TestBatch *batch = (TestBatch*)self;
-    PASS(batch, "placeholder");
+TestDocWriter_run(TestDocWriter *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    PASS(runner, "placeholder");
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Index/TestDocWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestDocWriter.cfh b/core/Lucy/Test/Index/TestDocWriter.cfh
index 1426d1c..8d9b2a1 100644
--- a/core/Lucy/Test/Index/TestDocWriter.cfh
+++ b/core/Lucy/Test/Index/TestDocWriter.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Index::TestDocWriter
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestDocWriter*
-    new(TestFormatter *formatter);
-
-    inert TestDocWriter*
-    init(TestDocWriter *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestDocWriter *self);
+    Run(TestDocWriter *self, TestBatchRunner *runner);
 }
 
 


[lucy-commits] [11/26] git commit: refs/heads/separate-clownfish-wip2 - Add is_included member to CFCParcel

Posted by nw...@apache.org.
Add is_included member to CFCParcel

Needed to tell whether a parcel is from an include directory. Also add
CFCParcel_source_parcels which list all non-included parcels from source
directories.

TODO: Fix Perl bindings


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/577de073
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/577de073
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/577de073

Branch: refs/heads/separate-clownfish-wip2
Commit: 577de07347f9207f933ad1ca8efba905b22bf260
Parents: 05fa068
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 20 22:36:34 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:17 2013 +0200

----------------------------------------------------------------------
 clownfish/compiler/perl/lib/Clownfish/CFC.xs |    6 +-
 clownfish/compiler/src/CFCHierarchy.c        |   18 +++++--
 clownfish/compiler/src/CFCParcel.c           |   52 +++++++++++++++++----
 clownfish/compiler/src/CFCParcel.h           |   19 ++++++--
 clownfish/compiler/src/CFCParseHeader.y      |    7 ++-
 clownfish/compiler/src/CFCTestClass.c        |    7 ++-
 clownfish/compiler/src/CFCTestParcel.c       |   22 +++++++--
 clownfish/compiler/src/CFCTestParser.c       |    8 +++-
 clownfish/compiler/src/CFCTestSymbol.c       |   12 ++++-
 clownfish/compiler/src/CFCTestType.c         |    9 ++--
 10 files changed, 123 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC.xs b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
index 347ccca..6d3f4f2 100644
--- a/clownfish/compiler/perl/lib/Clownfish/CFC.xs
+++ b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
@@ -1041,7 +1041,7 @@ _new(name_sv, cnick_sv, version)
 CODE:
     const char *name  = SvOK(name_sv)  ? SvPV_nolen(name_sv)  : NULL;
     const char *cnick = SvOK(cnick_sv) ? SvPV_nolen(cnick_sv) : NULL;
-    CFCParcel *self = CFCParcel_new(name, cnick, version);
+    CFCParcel *self = CFCParcel_new(name, cnick, version, false);
     RETVAL = S_cfcbase_to_perlref(self);
     CFCBase_decref((CFCBase*)self);
 OUTPUT: RETVAL
@@ -1050,7 +1050,7 @@ SV*
 _new_from_file(path)
     const char *path;
 CODE:
-    CFCParcel *self = CFCParcel_new_from_file(path);
+    CFCParcel *self = CFCParcel_new_from_file(path, false);
     RETVAL = S_cfcbase_to_perlref(self);
     CFCBase_decref((CFCBase*)self);
 OUTPUT: RETVAL
@@ -1059,7 +1059,7 @@ SV*
 _new_from_json(json)
     const char *json;
 CODE:
-    CFCParcel *self = CFCParcel_new_from_json(json);
+    CFCParcel *self = CFCParcel_new_from_json(json, false);
     RETVAL = S_cfcbase_to_perlref(self);
     CFCBase_decref((CFCBase*)self);
 OUTPUT: RETVAL

http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/src/CFCHierarchy.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCHierarchy.c b/clownfish/compiler/src/CFCHierarchy.c
index 5c5b192..f5d40eb 100644
--- a/clownfish/compiler/src/CFCHierarchy.c
+++ b/clownfish/compiler/src/CFCHierarchy.c
@@ -58,6 +58,10 @@ struct CFCHierarchy {
     size_t num_classes;
 };
 
+typedef struct CFCParseParcelFilesContext {
+    int is_included;
+} CFCParseParcelFilesContext;
+
 // CFCUtil_walk() callback which parses .cfp files.
 static void
 S_parse_parcel_files(const char *path, void *context);
@@ -185,11 +189,14 @@ CFCHierarchy_add_include_dir(CFCHierarchy *self, const char *include_dir) {
 
 void
 CFCHierarchy_build(CFCHierarchy *self) {
+    CFCParseParcelFilesContext context;
+    context.is_included = false;
     for (size_t i = 0; self->sources[i] != NULL; i++) {
-        CFCUtil_walk(self->sources[i], S_parse_parcel_files, NULL);
+        CFCUtil_walk(self->sources[i], S_parse_parcel_files, &context);
     }
+    context.is_included = false;
     for (size_t i = 0; self->includes[i] != NULL; i++) {
-        CFCUtil_walk(self->includes[i], S_parse_parcel_files, NULL);
+        CFCUtil_walk(self->includes[i], S_parse_parcel_files, &context);
     }
     for (size_t i = 0; self->sources[i] != NULL; i++) {
         S_parse_cf_files(self, self->sources[i], 0);
@@ -207,8 +214,8 @@ CFCHierarchy_build(CFCHierarchy *self) {
 }
 
 static void
-S_parse_parcel_files(const char *path, void *context) {
-    (void)context; // unused
+S_parse_parcel_files(const char *path, void *arg) {
+    CFCParseParcelFilesContext *context = (CFCParseParcelFilesContext*)arg;
 
     // Ignore hidden files.
     if (strstr(path, CHY_DIR_SEP ".") != NULL) {
@@ -218,7 +225,8 @@ S_parse_parcel_files(const char *path, void *context) {
     // Parse .cfp files and register the parcels they define.
     size_t path_len = strlen(path);
     if (path_len > 4 && (strcmp((path + path_len - 4), ".cfp") == 0)) {
-        CFCParcel *parcel = CFCParcel_new_from_file(path);
+        CFCParcel *parcel = CFCParcel_new_from_file(path,
+                                                    context->is_included);
         CFCParcel *existing = CFCParcel_fetch(CFCParcel_get_name(parcel));
         if (existing) {
             if (!CFCParcel_equals(parcel, existing)) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/src/CFCParcel.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParcel.c b/clownfish/compiler/src/CFCParcel.c
index 1cfe17e..f628f66 100644
--- a/clownfish/compiler/src/CFCParcel.c
+++ b/clownfish/compiler/src/CFCParcel.c
@@ -37,6 +37,7 @@ struct CFCParcel {
     char *prefix;
     char *Prefix;
     char *PREFIX;
+    int is_included;
 };
 
 static CFCParcel *default_parcel = NULL;
@@ -105,6 +106,27 @@ CFCParcel_register(CFCParcel *self) {
     registry[num_registered]   = NULL;
 }
 
+CFCParcel**
+CFCParcel_source_parcels(void) {
+    size_t size = (num_registered + 1) * sizeof(CFCParcel*);
+    CFCParcel **parcels = (CFCParcel**)MALLOCATE(size);
+    size_t n = 0;
+
+    for (size_t i = 0; registry[i]; ++i) {
+        CFCParcel  *parcel = registry[i];
+        const char *prefix = CFCParcel_get_prefix(parcel);
+
+        // Skip default and included parcels.
+        if (*prefix && !CFCParcel_included(parcel)) {
+            parcels[n++] = parcel;
+        }
+    }
+
+    parcels[n] = NULL;
+
+    return parcels;
+}
+
 void
 CFCParcel_reap_singletons(void) {
     for (size_t i = 0; i < num_registered; i++) {
@@ -133,14 +155,15 @@ static const CFCMeta CFCPARCEL_META = {
 };
 
 CFCParcel*
-CFCParcel_new(const char *name, const char *cnick, CFCVersion *version) {
+CFCParcel_new(const char *name, const char *cnick, CFCVersion *version,
+              int is_included) {
     CFCParcel *self = (CFCParcel*)CFCBase_allocate(&CFCPARCEL_META);
-    return CFCParcel_init(self, name, cnick, version);
+    return CFCParcel_init(self, name, cnick, version, is_included);
 }
 
 CFCParcel*
 CFCParcel_init(CFCParcel *self, const char *name, const char *cnick,
-               CFCVersion *version) {
+               CFCVersion *version, int is_included) {
     // Validate name.
     if (!name || !S_validate_name_or_cnick(name)) {
         CFCUtil_die("Invalid name: '%s'", name ? name : "[NULL]");
@@ -190,11 +213,14 @@ CFCParcel_init(CFCParcel *self, const char *name, const char *cnick,
     self->Prefix[prefix_len] = '\0';
     self->PREFIX[prefix_len] = '\0';
 
+    // Set is_included.
+    self->is_included = is_included;
+
     return self;
 }
 
 static CFCParcel*
-S_new_from_json(const char *json, const char *path) {
+S_new_from_json(const char *json, const char *path, int is_included) {
     JSONNode *parsed = S_parse_json_for_parcel(json);
     if (!parsed) {
         CFCUtil_die("Invalid JSON parcel definition in '%s'", path);
@@ -235,7 +261,7 @@ S_new_from_json(const char *json, const char *path) {
     if (!version) {
         CFCUtil_die("Missing required key 'version' (filepath '%s')", path);
     }
-    CFCParcel *self = CFCParcel_new(name, nickname, version);
+    CFCParcel *self = CFCParcel_new(name, nickname, version, is_included);
     CFCBase_decref((CFCBase*)version);
 
     for (size_t i = 0, max = parsed->num_kids; i < max; i += 2) {
@@ -257,15 +283,15 @@ S_new_from_json(const char *json, const char *path) {
 }
 
 CFCParcel*
-CFCParcel_new_from_json(const char *json) {
-    return S_new_from_json(json, "[NULL]");
+CFCParcel_new_from_json(const char *json, int is_included) {
+    return S_new_from_json(json, "[NULL]", is_included);
 }
 
 CFCParcel*
-CFCParcel_new_from_file(const char *path) {
+CFCParcel_new_from_file(const char *path, int is_included) {
     size_t len;
     char *json = CFCUtil_slurp_text(path, &len);
-    CFCParcel *self = S_new_from_json(json, path);
+    CFCParcel *self = S_new_from_json(json, path, is_included);
     FREEMEM(json);
     return self;
 }
@@ -284,7 +310,7 @@ CFCParcel_destroy(CFCParcel *self) {
 CFCParcel*
 CFCParcel_default_parcel(void) {
     if (default_parcel == NULL) {
-        default_parcel = CFCParcel_new("", "", NULL);
+        default_parcel = CFCParcel_new("", "", NULL, false);
     }
     return default_parcel;
 }
@@ -296,6 +322,7 @@ CFCParcel_equals(CFCParcel *self, CFCParcel *other) {
     if (CFCVersion_compare_to(self->version, other->version) != 0) {
         return false;
     }
+    if (self->is_included != other->is_included) { return false; }
     return true;
 }
 
@@ -329,6 +356,11 @@ CFCParcel_get_PREFIX(CFCParcel *self) {
     return self->PREFIX;
 }
 
+int
+CFCParcel_included(CFCParcel *self) {
+    return self->is_included;
+}
+
 /*****************************************************************************
  * The hack JSON parser coded up below is only meant to parse Clownfish parcel
  * file content.  It is limited in its capabilities because so little is legal

http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/src/CFCParcel.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParcel.h b/clownfish/compiler/src/CFCParcel.h
index 9ea3a4a..e77e5a8 100644
--- a/clownfish/compiler/src/CFCParcel.h
+++ b/clownfish/compiler/src/CFCParcel.h
@@ -50,6 +50,12 @@ CFCParcel_fetch(const char *name);
 void
 CFCParcel_register(CFCParcel *self);
 
+/** Return a NULL-terminated list of all registered parcels that are not
+ * included. Must be freed by the caller.
+ */
+CFCParcel**
+CFCParcel_source_parcels(void);
+
 /** Decref all singletons at shutdown.
  */
 void
@@ -57,17 +63,17 @@ CFCParcel_reap_singletons(void);
 
 CFCParcel*
 CFCParcel_new(const char *name, const char *cnick,
-              struct CFCVersion *version);
+              struct CFCVersion *version, int is_included);
 
 CFCParcel*
-CFCParcel_new_from_file(const char *path);
+CFCParcel_new_from_file(const char *path, int is_included);
 
 CFCParcel*
-CFCParcel_new_from_json(const char *json);
+CFCParcel_new_from_json(const char *json, int is_included);
 
 CFCParcel*
 CFCParcel_init(CFCParcel *self, const char *name, const char *cnick,
-               struct CFCVersion *version);
+               struct CFCVersion *version, int is_included);
 
 void
 CFCParcel_destroy(CFCParcel *self);
@@ -104,6 +110,11 @@ CFCParcel_get_Prefix(CFCParcel *self);
 const char*
 CFCParcel_get_PREFIX(CFCParcel *self);
 
+/** Return true if the parcel is from an include directory.
+ */
+int
+CFCParcel_included(CFCParcel *self);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/src/CFCParseHeader.y
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParseHeader.y b/clownfish/compiler/src/CFCParseHeader.y
index 9b14db5..c9f9215 100644
--- a/clownfish/compiler/src/CFCParseHeader.y
+++ b/clownfish/compiler/src/CFCParseHeader.y
@@ -315,7 +315,12 @@ parcel_definition(A) ::= PARCEL qualified_id(B) SEMICOLON.
 {
     A = CFCParcel_fetch(B);
     if (!A) {
-        A = CFCParcel_new(B, NULL, NULL);
+        CFCFileSpec *file_spec = CFCParser_get_file_spec(state);
+        int is_included = false;
+        if (file_spec) {
+            is_included = CFCFileSpec_included(file_spec);
+        }
+        A = CFCParcel_new(B, NULL, NULL, is_included);
         CFCParcel_register(A);
         CFCBase_decref((CFCBase*)A);
     }

http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/src/CFCTestClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestClass.c b/clownfish/compiler/src/CFCTestClass.c
index 9f841f9..2eb4183 100644
--- a/clownfish/compiler/src/CFCTestClass.c
+++ b/clownfish/compiler/src/CFCTestClass.c
@@ -31,6 +31,11 @@
 #include "CFCUtil.h"
 #include "CFCVariable.h"
 
+#ifndef true
+  #define true 1
+  #define false 0
+#endif
+
 static void
 S_run_tests(CFCTest *test);
 
@@ -47,7 +52,7 @@ static void
 S_run_tests(CFCTest *test) {
     CFCParser *parser = CFCParser_new();
 
-    CFCParcel *neato = CFCParcel_new("Neato", NULL, NULL);
+    CFCParcel *neato = CFCParcel_new("Neato", NULL, NULL, false);
     CFCFileSpec *file_spec = CFCFileSpec_new(".", "Foo/FooJr", 0);
     CFCClass *thing_class
         = CFCTest_parse_class(test, parser, "class Thing {}");

http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/src/CFCTestParcel.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestParcel.c b/clownfish/compiler/src/CFCTestParcel.c
index e468e9f..9c63f18 100644
--- a/clownfish/compiler/src/CFCTestParcel.c
+++ b/clownfish/compiler/src/CFCTestParcel.c
@@ -23,20 +23,32 @@
 #include "CFCVersion.h"
 #include "CFCTest.h"
 
+#ifndef true
+  #define true 1
+  #define false 0
+#endif
+
 static void
 S_run_tests(CFCTest *test);
 
 const CFCTestBatch CFCTEST_BATCH_PARCEL = {
     "Clownfish::CFC::Model::Parcel",
-    10,
+    12,
     S_run_tests
 };
 
 static void
 S_run_tests(CFCTest *test) {
     {
-        CFCParcel *parcel = CFCParcel_new("Foo", NULL, NULL);
+        CFCParcel *parcel = CFCParcel_new("Foo", NULL, NULL, false);
         OK(test, parcel != NULL, "new");
+        OK(test, !CFCParcel_included(parcel), "not included");
+        CFCBase_decref((CFCBase*)parcel);
+    }
+
+    {
+        CFCParcel *parcel = CFCParcel_new("Foo", NULL, NULL, true);
+        OK(test, CFCParcel_included(parcel), "included");
         CFCBase_decref((CFCBase*)parcel);
     }
 
@@ -47,14 +59,14 @@ S_run_tests(CFCTest *test) {
             "            \"nickname\": \"Crust\",\n"
             "            \"version\": \"v0.1.0\"\n"
             "        }\n";
-        CFCParcel *parcel = CFCParcel_new_from_json(json);
+        CFCParcel *parcel = CFCParcel_new_from_json(json, false);
         OK(test, parcel != NULL, "new_from_json");
         CFCBase_decref((CFCBase*)parcel);
     }
 
     {
         const char *path = "t" CHY_DIR_SEP "cfsource" CHY_DIR_SEP "Animal.cfp";
-        CFCParcel *parcel = CFCParcel_new_from_file(path);
+        CFCParcel *parcel = CFCParcel_new_from_file(path, false);
         OK(test, parcel != NULL, "new_from_file");
         CFCBase_decref((CFCBase*)parcel);
     }
@@ -72,7 +84,7 @@ S_run_tests(CFCTest *test) {
     }
 
     {
-        CFCParcel *parcel = CFCParcel_new("Crustacean", "Crust", NULL);
+        CFCParcel *parcel = CFCParcel_new("Crustacean", "Crust", NULL, false);
         CFCParcel_register(parcel);
         STR_EQ(test, CFCVersion_get_vstring(CFCParcel_get_version(parcel)),
                "v0", "get_version");

http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/src/CFCTestParser.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestParser.c b/clownfish/compiler/src/CFCTestParser.c
index 46611dd..04c39e7 100644
--- a/clownfish/compiler/src/CFCTestParser.c
+++ b/clownfish/compiler/src/CFCTestParser.c
@@ -27,6 +27,11 @@
 #include "CFCUtil.h"
 #include "CFCVariable.h"
 
+#ifndef true
+  #define true 1
+  #define false 0
+#endif
+
 static void
 S_run_tests(CFCTest *test);
 
@@ -49,7 +54,8 @@ S_run_tests(CFCTest *test) {
     {
         CFCParcel *fish = CFCTest_parse_parcel(test, parser, "parcel Fish;");
 
-        CFCParcel *registered = CFCParcel_new("Crustacean", "Crust", NULL);
+        CFCParcel *registered
+            = CFCParcel_new("Crustacean", "Crust", NULL, false);
         CFCParcel_register(registered);
         CFCParcel *parcel
             = CFCTest_parse_parcel(test, parser, "parcel Crustacean;");

http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/src/CFCTestSymbol.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestSymbol.c b/clownfish/compiler/src/CFCTestSymbol.c
index 7dfe8d9..8f6518e 100644
--- a/clownfish/compiler/src/CFCTestSymbol.c
+++ b/clownfish/compiler/src/CFCTestSymbol.c
@@ -20,6 +20,11 @@
 #include "CFCSymbol.h"
 #include "CFCTest.h"
 
+#ifndef true
+  #define true 1
+  #define false 0
+#endif
+
 static void
 S_run_tests(CFCTest *test);
 
@@ -89,7 +94,8 @@ S_run_tests(CFCTest *test) {
     }
 
     {
-        CFCParcel *lucifer_parcel = CFCParcel_new("Lucifer", NULL, NULL);
+        CFCParcel *lucifer_parcel
+            = CFCParcel_new("Lucifer", NULL, NULL, false);
         CFCParcel_register(lucifer_parcel);
         CFCSymbol *lucifer
             = CFCSymbol_new(lucifer_parcel, "parcel", NULL, NULL, "sym");
@@ -103,7 +109,7 @@ S_run_tests(CFCTest *test) {
         const char *PREFIX = CFCSymbol_get_PREFIX(lucifer);
         STR_EQ(test, PREFIX, "LUCIFER_", "get_PREFIX");
 
-        CFCParcel *luser_parcel = CFCParcel_new("Luser", NULL, NULL);
+        CFCParcel *luser_parcel = CFCParcel_new("Luser", NULL, NULL, false);
         CFCParcel_register(luser_parcel);
         CFCSymbol *luser
             = CFCSymbol_new(luser_parcel, "parcel", NULL, NULL, "sym");
@@ -127,7 +133,7 @@ S_run_tests(CFCTest *test) {
     }
 
     {
-        CFCParcel *eep_parcel = CFCParcel_new("Eep", NULL, NULL);
+        CFCParcel *eep_parcel = CFCParcel_new("Eep", NULL, NULL, false);
         CFCParcel_register(eep_parcel);
         CFCSymbol *eep
             = CFCSymbol_new(eep_parcel, "parcel", "Op::Ork", NULL, "ah_ah");

http://git-wip-us.apache.org/repos/asf/lucy/blob/577de073/clownfish/compiler/src/CFCTestType.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestType.c b/clownfish/compiler/src/CFCTestType.c
index 759aa42..9dc135f 100644
--- a/clownfish/compiler/src/CFCTestType.c
+++ b/clownfish/compiler/src/CFCTestType.c
@@ -79,7 +79,7 @@ S_run_tests(CFCTest *test) {
 
 static void
 S_run_basic_tests(CFCTest *test) {
-    CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL);
+    CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL, false);
     CFCParcel_register(neato_parcel);
     CFCType *type = CFCType_new(0, neato_parcel, "mytype_t", 0, NULL);
 
@@ -333,7 +333,7 @@ S_run_object_tests(CFCTest *test) {
         CFCBase_decref((CFCBase*)parser);
     }
 
-    CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL);
+    CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL, false);
     CFCClass *foo_class
         = CFCClass_create(neato_parcel, NULL, "Foo", NULL, NULL, NULL, NULL,
                           NULL, false, false);
@@ -356,7 +356,8 @@ S_run_object_tests(CFCTest *test) {
     }
 
     {
-        CFCParcel *foreign_parcel = CFCParcel_new("Foreign", NULL, NULL);
+        CFCParcel *foreign_parcel
+            = CFCParcel_new("Foreign", NULL, NULL, false);
         CFCClass *foreign_foo_class
             = CFCClass_create(foreign_parcel, NULL, "Foo", NULL, NULL, NULL,
                               NULL, NULL, false, false);
@@ -423,7 +424,7 @@ S_run_va_list_tests(CFCTest *test) {
 static void
 S_run_arbitrary_tests(CFCTest *test) {
     {
-        CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL);
+        CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL, false);
         CFCParcel_register(neato_parcel);
 
         CFCType *foo = CFCType_new_arbitrary(neato_parcel, "foo_t");


[lucy-commits] [07/26] Move Clownfish runtime tests to a separate parcel

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestHash.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestHash.c b/core/Lucy/Test/Object/TestHash.c
deleted file mode 100644
index 635d8e1..0000000
--- a/core/Lucy/Test/Object/TestHash.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Lucy/Util/ToolSet.h"
-#include <stdlib.h>
-#include <time.h>
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/TestUtils.h"
-#include "Lucy/Test/Object/TestHash.h"
-#include "Clownfish/Hash.h"
-
-TestHash*
-TestHash_new(TestFormatter *formatter) {
-    TestHash *self = (TestHash*)VTable_Make_Obj(TESTHASH);
-    return TestHash_init(self, formatter);
-}
-
-TestHash*
-TestHash_init(TestHash *self, TestFormatter *formatter) {
-    return (TestHash*)TestBatch_init((TestBatch*)self, 29, formatter);
-}
-
-static void
-test_Equals(TestBatch *batch) {
-    Hash *hash  = Hash_new(0);
-    Hash *other = Hash_new(0);
-    ZombieCharBuf *stuff = ZCB_WRAP_STR("stuff", 5);
-
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)other),
-              "Empty hashes are equal");
-
-    Hash_Store_Str(hash, "foo", 3, (Obj*)CFISH_TRUE);
-    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)other),
-               "Add one pair and Equals returns false");
-
-    Hash_Store_Str(other, "foo", 3, (Obj*)CFISH_TRUE);
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)other),
-              "Add a matching pair and Equals returns true");
-
-    Hash_Store_Str(other, "foo", 3, INCREF(stuff));
-    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)other),
-               "Non-matching value spoils Equals");
-
-    DECREF(hash);
-    DECREF(other);
-}
-
-static void
-test_Store_and_Fetch(TestBatch *batch) {
-    Hash          *hash         = Hash_new(100);
-    Hash          *dupe         = Hash_new(100);
-    const uint32_t starting_cap = Hash_Get_Capacity(hash);
-    VArray        *expected     = VA_new(100);
-    VArray        *got          = VA_new(100);
-    ZombieCharBuf *twenty       = ZCB_WRAP_STR("20", 2);
-    ZombieCharBuf *forty        = ZCB_WRAP_STR("40", 2);
-    ZombieCharBuf *foo          = ZCB_WRAP_STR("foo", 3);
-
-    for (int32_t i = 0; i < 100; i++) {
-        CharBuf *cb = CB_newf("%i32", i);
-        Hash_Store(hash, (Obj*)cb, (Obj*)cb);
-        Hash_Store(dupe, (Obj*)cb, INCREF(cb));
-        VA_Push(expected, INCREF(cb));
-    }
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)dupe), "Equals");
-
-    TEST_INT_EQ(batch, Hash_Get_Capacity(hash), starting_cap,
-                "Initial capacity sufficient (no rebuilds)");
-
-    for (int32_t i = 0; i < 100; i++) {
-        Obj *key  = VA_Fetch(expected, i);
-        Obj *elem = Hash_Fetch(hash, key);
-        VA_Push(got, (Obj*)INCREF(elem));
-    }
-
-    TEST_TRUE(batch, VA_Equals(got, (Obj*)expected),
-              "basic Store and Fetch");
-    TEST_INT_EQ(batch, Hash_Get_Size(hash), 100,
-                "size incremented properly by Hash_Store");
-
-    TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)foo) == NULL,
-              "Fetch against non-existent key returns NULL");
-
-    Hash_Store(hash, (Obj*)forty, INCREF(foo));
-    TEST_TRUE(batch, ZCB_Equals(foo, Hash_Fetch(hash, (Obj*)forty)),
-              "Hash_Store replaces existing value");
-    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)dupe),
-               "replacement value spoils equals");
-    TEST_INT_EQ(batch, Hash_Get_Size(hash), 100,
-                "size unaffected after value replaced");
-
-    TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == (Obj*)foo,
-              "Delete returns value");
-    DECREF(foo);
-    TEST_INT_EQ(batch, Hash_Get_Size(hash), 99,
-                "size decremented by successful Delete");
-    TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == NULL,
-              "Delete returns NULL when key not found");
-    TEST_INT_EQ(batch, Hash_Get_Size(hash), 99,
-                "size not decremented by unsuccessful Delete");
-    DECREF(Hash_Delete(dupe, (Obj*)forty));
-    TEST_TRUE(batch, VA_Equals(got, (Obj*)expected), "Equals after Delete");
-
-    Hash_Clear(hash);
-    TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)twenty) == NULL, "Clear");
-    TEST_TRUE(batch, Hash_Get_Size(hash) == 0, "size is 0 after Clear");
-
-    DECREF(hash);
-    DECREF(dupe);
-    DECREF(got);
-    DECREF(expected);
-}
-
-static void
-test_Keys_Values_Iter(TestBatch *batch) {
-    Hash     *hash     = Hash_new(0); // trigger multiple rebuilds.
-    VArray   *expected = VA_new(100);
-    VArray   *keys;
-    VArray   *values;
-
-    for (uint32_t i = 0; i < 500; i++) {
-        CharBuf *cb = CB_newf("%u32", i);
-        Hash_Store(hash, (Obj*)cb, (Obj*)cb);
-        VA_Push(expected, INCREF(cb));
-    }
-
-    VA_Sort(expected, NULL, NULL);
-
-    keys   = Hash_Keys(hash);
-    values = Hash_Values(hash);
-    VA_Sort(keys, NULL, NULL);
-    VA_Sort(values, NULL, NULL);
-    TEST_TRUE(batch, VA_Equals(keys, (Obj*)expected), "Keys");
-    TEST_TRUE(batch, VA_Equals(values, (Obj*)expected), "Values");
-    VA_Clear(keys);
-    VA_Clear(values);
-
-    {
-        Obj *key;
-        Obj *value;
-        Hash_Iterate(hash);
-        while (Hash_Next(hash, &key, &value)) {
-            VA_Push(keys, INCREF(key));
-            VA_Push(values, INCREF(value));
-        }
-    }
-
-    VA_Sort(keys, NULL, NULL);
-    VA_Sort(values, NULL, NULL);
-    TEST_TRUE(batch, VA_Equals(keys, (Obj*)expected), "Keys from Iter");
-    TEST_TRUE(batch, VA_Equals(values, (Obj*)expected), "Values from Iter");
-
-    {
-        ZombieCharBuf *forty = ZCB_WRAP_STR("40", 2);
-        ZombieCharBuf *nope  = ZCB_WRAP_STR("nope", 4);
-        Obj *key = Hash_Find_Key(hash, (Obj*)forty, ZCB_Hash_Sum(forty));
-        TEST_TRUE(batch, Obj_Equals(key, (Obj*)forty), "Find_Key");
-        key = Hash_Find_Key(hash, (Obj*)nope, ZCB_Hash_Sum(nope)),
-        TEST_TRUE(batch, key == NULL,
-                  "Find_Key returns NULL for non-existent key");
-    }
-
-    DECREF(hash);
-    DECREF(expected);
-    DECREF(keys);
-    DECREF(values);
-}
-
-static void
-test_Dump_and_Load(TestBatch *batch) {
-    Hash *hash = Hash_new(0);
-    Obj  *dump;
-    Hash *loaded;
-
-    Hash_Store_Str(hash, "foo", 3,
-                   (Obj*)CB_new_from_trusted_utf8("foo", 3));
-    dump = (Obj*)Hash_Dump(hash);
-    loaded = (Hash*)Obj_Load(dump, dump);
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)loaded),
-              "Dump => Load round trip");
-    DECREF(dump);
-    DECREF(loaded);
-
-    /* TODO: Fix Hash_Load().
-
-    Hash_Store_Str(hash, "_class", 6,
-        (Obj*)CB_new_from_trusted_utf8("not_a_class", 11));
-    dump = (Obj*)Hash_Dump(hash);
-    loaded = (Hash*)Obj_Load(dump, dump);
-
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)loaded),
-              "Load still works with _class if it's not a real class");
-    DECREF(dump);
-    DECREF(loaded);
-
-    */
-
-    DECREF(hash);
-}
-
-static void
-test_serialization(TestBatch *batch) {
-    Hash  *wanted = Hash_new(0);
-    Hash  *got;
-
-    for (uint32_t i = 0; i < 10; i++) {
-        CharBuf *cb = TestUtils_random_string(rand() % 1200);
-        Integer32 *num = Int32_new(i);
-        Hash_Store(wanted, (Obj*)cb, (Obj*)num);
-        Hash_Store(wanted, (Obj*)num, (Obj*)cb);
-    }
-
-    got = (Hash*)TestUtils_freeze_thaw((Obj*)wanted);
-    TEST_TRUE(batch, got && Hash_Equals(wanted, (Obj*)got),
-              "Round trip through serialization.");
-
-    DECREF(got);
-    DECREF(wanted);
-}
-
-static void
-test_stress(TestBatch *batch) {
-    Hash     *hash     = Hash_new(0); // trigger multiple rebuilds.
-    VArray   *expected = VA_new(1000);
-    VArray   *keys;
-    VArray   *values;
-
-    for (uint32_t i = 0; i < 1000; i++) {
-        CharBuf *cb = TestUtils_random_string(rand() % 1200);
-        while (Hash_Fetch(hash, (Obj*)cb)) {
-            DECREF(cb);
-            cb = TestUtils_random_string(rand() % 1200);
-        }
-        Hash_Store(hash, (Obj*)cb, (Obj*)cb);
-        VA_Push(expected, INCREF(cb));
-    }
-
-    VA_Sort(expected, NULL, NULL);
-
-    // Overwrite for good measure.
-    for (uint32_t i = 0; i < 1000; i++) {
-        CharBuf *cb = (CharBuf*)VA_Fetch(expected, i);
-        Hash_Store(hash, (Obj*)cb, INCREF(cb));
-    }
-
-    keys   = Hash_Keys(hash);
-    values = Hash_Values(hash);
-    VA_Sort(keys, NULL, NULL);
-    VA_Sort(values, NULL, NULL);
-    TEST_TRUE(batch, VA_Equals(keys, (Obj*)expected), "stress Keys");
-    TEST_TRUE(batch, VA_Equals(values, (Obj*)expected), "stress Values");
-
-    DECREF(keys);
-    DECREF(values);
-    DECREF(expected);
-    DECREF(hash);
-}
-
-void
-TestHash_run_tests(TestHash *self) {
-    TestBatch *batch = (TestBatch*)self;
-    srand((unsigned int)time((time_t*)NULL));
-    test_Equals(batch);
-    test_Store_and_Fetch(batch);
-    test_Keys_Values_Iter(batch);
-    test_Dump_and_Load(batch);
-    test_serialization(batch);
-    test_stress(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestHash.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestHash.cfh b/core/Lucy/Test/Object/TestHash.cfh
deleted file mode 100644
index 95dd31d..0000000
--- a/core/Lucy/Test/Object/TestHash.cfh
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Object::TestHash
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestHash*
-    new(TestFormatter *formatter);
-
-    inert TestHash*
-    init(TestHash *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestHash *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestLockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestLockFreeRegistry.c b/core/Lucy/Test/Object/TestLockFreeRegistry.c
deleted file mode 100644
index 3e1ffe4..0000000
--- a/core/Lucy/Test/Object/TestLockFreeRegistry.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string.h>
-
-#include "Lucy/Util/ToolSet.h"
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/TestUtils.h"
-#include "Lucy/Test/Object/TestLockFreeRegistry.h"
-#include "Clownfish/LockFreeRegistry.h"
-
-TestLockFreeRegistry*
-TestLFReg_new(TestFormatter *formatter) {
-    TestLockFreeRegistry *self = (TestLockFreeRegistry*)VTable_Make_Obj(TESTLOCKFREEREGISTRY);
-    return TestLFReg_init(self, formatter);
-}
-
-TestLockFreeRegistry*
-TestLFReg_init(TestLockFreeRegistry *self, TestFormatter *formatter) {
-    return (TestLockFreeRegistry*)TestBatch_init((TestBatch*)self, 6, formatter);
-}
-
-StupidHashCharBuf*
-StupidHashCharBuf_new(const char *text) {
-    return (StupidHashCharBuf*)CB_new_from_utf8(text, strlen(text));
-}
-
-int32_t
-StupidHashCharBuf_hash_sum(StupidHashCharBuf *self) {
-    UNUSED_VAR(self);
-    return 1;
-}
-
-static void
-test_all(TestBatch *batch) {
-    LockFreeRegistry *registry = LFReg_new(10);
-    StupidHashCharBuf *foo = StupidHashCharBuf_new("foo");
-    StupidHashCharBuf *bar = StupidHashCharBuf_new("bar");
-    StupidHashCharBuf *baz = StupidHashCharBuf_new("baz");
-    StupidHashCharBuf *foo_dupe = StupidHashCharBuf_new("foo");
-
-    TEST_TRUE(batch, LFReg_Register(registry, (Obj*)foo, (Obj*)foo),
-              "Register() returns true on success");
-    TEST_FALSE(batch,
-               LFReg_Register(registry, (Obj*)foo_dupe, (Obj*)foo_dupe),
-               "Can't Register() keys that test equal");
-
-    TEST_TRUE(batch, LFReg_Register(registry, (Obj*)bar, (Obj*)bar),
-              "Register() key with the same Hash_Sum but that isn't Equal");
-
-    TEST_TRUE(batch, LFReg_Fetch(registry, (Obj*)foo_dupe) == (Obj*)foo,
-              "Fetch()");
-    TEST_TRUE(batch, LFReg_Fetch(registry, (Obj*)bar) == (Obj*)bar,
-              "Fetch() again");
-    TEST_TRUE(batch, LFReg_Fetch(registry, (Obj*)baz) == NULL,
-              "Fetch() non-existent key returns NULL");
-
-    DECREF(foo_dupe);
-    DECREF(baz);
-    DECREF(bar);
-    DECREF(foo);
-    DECREF(registry);
-}
-
-void
-TestLFReg_run_tests(TestLockFreeRegistry *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_all(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestLockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestLockFreeRegistry.cfh b/core/Lucy/Test/Object/TestLockFreeRegistry.cfh
deleted file mode 100644
index f73cd91..0000000
--- a/core/Lucy/Test/Object/TestLockFreeRegistry.cfh
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Object::TestLockFreeRegistry cnick TestLFReg
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestLockFreeRegistry*
-    new(TestFormatter *formatter);
-
-    inert TestLockFreeRegistry*
-    init(TestLockFreeRegistry *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestLockFreeRegistry *self);
-}
-
-/** Private test-only class for stressing LockFreeRegistry.
- */
-class Lucy::Test::Object::StupidHashCharBuf inherits Clownfish::CharBuf {
-    inert incremented StupidHashCharBuf*
-    new(const char *text);
-
-    /** Always returns 1, guaranteeing collisions. */
-    public int32_t
-    Hash_Sum(StupidHashCharBuf *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestNum.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestNum.c b/core/Lucy/Test/Object/TestNum.c
deleted file mode 100644
index a76b058..0000000
--- a/core/Lucy/Test/Object/TestNum.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_LUCY_TESTNUM
-#include "Lucy/Util/ToolSet.h"
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/TestUtils.h"
-#include "Lucy/Test/Object/TestNum.h"
-
-TestNum*
-TestNum_new(TestFormatter *formatter) {
-    TestNum *self = (TestNum*)VTable_Make_Obj(TESTNUM);
-    return TestNum_init(self, formatter);
-}
-
-TestNum*
-TestNum_init(TestNum *self, TestFormatter *formatter) {
-    return (TestNum*)TestBatch_init((TestBatch*)self, 58, formatter);
-}
-
-static void
-test_To_String(TestBatch *batch) {
-    Float32   *f32 = Float32_new(1.33f);
-    Float64   *f64 = Float64_new(1.33);
-    Integer32 *i32 = Int32_new(INT32_MAX);
-    Integer64 *i64 = Int64_new(INT64_MAX);
-    CharBuf *f32_string = Float32_To_String(f32);
-    CharBuf *f64_string = Float64_To_String(f64);
-    CharBuf *i32_string = Int32_To_String(i32);
-    CharBuf *i64_string = Int64_To_String(i64);
-    CharBuf *true_string  = Bool_To_String(CFISH_TRUE);
-    CharBuf *false_string = Bool_To_String(CFISH_FALSE);
-
-    TEST_TRUE(batch, CB_Starts_With_Str(f32_string, "1.3", 3),
-              "Float32_To_String");
-    TEST_TRUE(batch, CB_Starts_With_Str(f64_string, "1.3", 3),
-              "Float64_To_String");
-    TEST_TRUE(batch, CB_Equals_Str(i32_string, "2147483647", 10),
-              "Int32_To_String");
-    TEST_TRUE(batch, CB_Equals_Str(i64_string, "9223372036854775807", 19),
-              "Int64_To_String");
-    TEST_TRUE(batch, CB_Equals_Str(true_string, "true", 4),
-              "Bool_To_String [true]");
-    TEST_TRUE(batch, CB_Equals_Str(false_string, "false", 5),
-              "Bool_To_String [false]");
-
-    DECREF(false_string);
-    DECREF(true_string);
-    DECREF(i64_string);
-    DECREF(i32_string);
-    DECREF(f64_string);
-    DECREF(f32_string);
-    DECREF(i64);
-    DECREF(i32);
-    DECREF(f64);
-    DECREF(f32);
-}
-
-static void
-test_accessors(TestBatch *batch) {
-    Float32   *f32 = Float32_new(1.0);
-    Float64   *f64 = Float64_new(1.0);
-    Integer32 *i32 = Int32_new(1);
-    Integer64 *i64 = Int64_new(1);
-    float  wanted32 = 1.33f;
-    double wanted64 = 1.33;
-    float  got32;
-    double got64;
-
-    Float32_Set_Value(f32, 1.33f);
-    TEST_FLOAT_EQ(batch, Float32_Get_Value(f32), 1.33f,
-                  "F32 Set_Value Get_Value");
-
-    Float64_Set_Value(f64, 1.33);
-    got64 = Float64_Get_Value(f64);
-    TEST_TRUE(batch, *(int64_t*)&got64 == *(int64_t*)&wanted64,
-              "F64 Set_Value Get_Value");
-
-    TEST_TRUE(batch, Float32_To_I64(f32) == 1, "Float32_To_I64");
-    TEST_TRUE(batch, Float64_To_I64(f64) == 1, "Float64_To_I64");
-
-    got32 = (float)Float32_To_F64(f32);
-    TEST_TRUE(batch, *(int32_t*)&got32 == *(int32_t*)&wanted32,
-              "Float32_To_F64");
-
-    got64 = Float64_To_F64(f64);
-    TEST_TRUE(batch, *(int64_t*)&got64 == *(int64_t*)&wanted64,
-              "Float64_To_F64");
-
-    Int32_Set_Value(i32, INT32_MIN);
-    TEST_INT_EQ(batch, Int32_Get_Value(i32), INT32_MIN,
-                "I32 Set_Value Get_Value");
-
-    Int64_Set_Value(i64, INT64_MIN);
-    TEST_TRUE(batch, Int64_Get_Value(i64) == INT64_MIN,
-              "I64 Set_Value Get_Value");
-
-    Int32_Set_Value(i32, -1);
-    Int64_Set_Value(i64, -1);
-    TEST_TRUE(batch, Int32_To_F64(i32) == -1, "Int32_To_F64");
-    TEST_TRUE(batch, Int64_To_F64(i64) == -1, "Int64_To_F64");
-
-    TEST_INT_EQ(batch, Bool_Get_Value(CFISH_TRUE), true,
-                "Bool_Get_Value [true]");
-    TEST_INT_EQ(batch, Bool_Get_Value(CFISH_FALSE), false,
-                "Bool_Get_Value [false]");
-    TEST_TRUE(batch, Bool_To_I64(CFISH_TRUE) == true,
-              "Bool_To_I64 [true]");
-    TEST_TRUE(batch, Bool_To_I64(CFISH_FALSE) == false,
-              "Bool_To_I64 [false]");
-    TEST_TRUE(batch, Bool_To_F64(CFISH_TRUE) == 1.0,
-              "Bool_To_F64 [true]");
-    TEST_TRUE(batch, Bool_To_F64(CFISH_FALSE) == 0.0,
-              "Bool_To_F64 [false]");
-
-    DECREF(i64);
-    DECREF(i32);
-    DECREF(f64);
-    DECREF(f32);
-}
-
-static void
-test_Equals_and_Compare_To(TestBatch *batch) {
-    Float32   *f32 = Float32_new(1.0);
-    Float64   *f64 = Float64_new(1.0);
-    Integer32 *i32 = Int32_new(INT32_MAX);
-    Integer64 *i64 = Int64_new(INT64_MAX);
-
-    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)f64) == 0,
-              "F32_Compare_To equal");
-    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f64),
-              "F32_Equals equal");
-
-    Float64_Set_Value(f64, 2.0);
-    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)f64) < 0,
-              "F32_Compare_To less than");
-    TEST_FALSE(batch, Float32_Equals(f32, (Obj*)f64),
-               "F32_Equals less than");
-
-    Float64_Set_Value(f64, 0.0);
-    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)f64) > 0,
-              "F32_Compare_To greater than");
-    TEST_FALSE(batch, Float32_Equals(f32, (Obj*)f64),
-               "F32_Equals greater than");
-
-    Float64_Set_Value(f64, 1.0);
-    Float32_Set_Value(f32, 1.0);
-    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)f32) == 0,
-              "F64_Compare_To equal");
-    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f32),
-              "F64_Equals equal");
-
-    Float32_Set_Value(f32, 2.0);
-    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)f32) < 0,
-              "F64_Compare_To less than");
-    TEST_FALSE(batch, Float64_Equals(f64, (Obj*)f32),
-               "F64_Equals less than");
-
-    Float32_Set_Value(f32, 0.0);
-    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)f32) > 0,
-              "F64_Compare_To greater than");
-    TEST_FALSE(batch, Float64_Equals(f64, (Obj*)f32),
-               "F64_Equals greater than");
-
-    Float64_Set_Value(f64, INT64_MAX * 2.0);
-    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)i64) > 0,
-              "Float64 comparison to Integer64");
-    TEST_TRUE(batch, Int64_Compare_To(i64, (Obj*)f64) < 0,
-              "Integer64 comparison to Float64");
-
-    Float32_Set_Value(f32, INT32_MAX * 2.0f);
-    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)i32) > 0,
-              "Float32 comparison to Integer32");
-    TEST_TRUE(batch, Int32_Compare_To(i32, (Obj*)f32) < 0,
-              "Integer32 comparison to Float32");
-
-    Int64_Set_Value(i64, INT64_C(0x6666666666666666));
-    Integer64 *i64_copy = Int64_new(INT64_C(0x6666666666666666));
-    TEST_TRUE(batch, Int64_Compare_To(i64, (Obj*)i64_copy) == 0,
-              "Integer64 comparison to same number");
-
-    TEST_TRUE(batch, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_TRUE),
-              "CFISH_TRUE Equals itself");
-    TEST_TRUE(batch, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_FALSE),
-              "CFISH_FALSE Equals itself");
-    TEST_FALSE(batch, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_TRUE),
-               "CFISH_FALSE not Equals CFISH_TRUE ");
-    TEST_FALSE(batch, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_FALSE),
-               "CFISH_TRUE not Equals CFISH_FALSE ");
-    TEST_FALSE(batch, Bool_Equals(CFISH_TRUE, (Obj*)CHARBUF),
-               "CFISH_TRUE not Equals random other object ");
-
-    DECREF(i64_copy);
-    DECREF(i64);
-    DECREF(i32);
-    DECREF(f64);
-    DECREF(f32);
-}
-
-static void
-test_Clone(TestBatch *batch) {
-    Float32   *f32 = Float32_new(1.33f);
-    Float64   *f64 = Float64_new(1.33);
-    Integer32 *i32 = Int32_new(INT32_MAX);
-    Integer64 *i64 = Int64_new(INT64_MAX);
-    Float32   *f32_dupe = Float32_Clone(f32);
-    Float64   *f64_dupe = Float64_Clone(f64);
-    Integer32 *i32_dupe = Int32_Clone(i32);
-    Integer64 *i64_dupe = Int64_Clone(i64);
-    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f32_dupe),
-              "Float32 Clone");
-    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f64_dupe),
-              "Float64 Clone");
-    TEST_TRUE(batch, Int32_Equals(i32, (Obj*)i32_dupe),
-              "Integer32 Clone");
-    TEST_TRUE(batch, Int64_Equals(i64, (Obj*)i64_dupe),
-              "Integer64 Clone");
-    TEST_TRUE(batch, Bool_Equals(CFISH_TRUE, (Obj*)Bool_Clone(CFISH_TRUE)),
-              "BoolNum Clone");
-    DECREF(i64_dupe);
-    DECREF(i32_dupe);
-    DECREF(f64_dupe);
-    DECREF(f32_dupe);
-    DECREF(i64);
-    DECREF(i32);
-    DECREF(f64);
-    DECREF(f32);
-}
-
-static void
-test_Mimic(TestBatch *batch) {
-    Float32   *f32 = Float32_new(1.33f);
-    Float64   *f64 = Float64_new(1.33);
-    Integer32 *i32 = Int32_new(INT32_MAX);
-    Integer64 *i64 = Int64_new(INT64_MAX);
-    Float32   *f32_dupe = Float32_new(0.0f);
-    Float64   *f64_dupe = Float64_new(0.0);
-    Integer32 *i32_dupe = Int32_new(0);
-    Integer64 *i64_dupe = Int64_new(0);
-    Float32_Mimic(f32_dupe, (Obj*)f32);
-    Float64_Mimic(f64_dupe, (Obj*)f64);
-    Int32_Mimic(i32_dupe, (Obj*)i32);
-    Int64_Mimic(i64_dupe, (Obj*)i64);
-    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f32_dupe),
-              "Float32 Mimic");
-    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f64_dupe),
-              "Float64 Mimic");
-    TEST_TRUE(batch, Int32_Equals(i32, (Obj*)i32_dupe),
-              "Integer32 Mimic");
-    TEST_TRUE(batch, Int64_Equals(i64, (Obj*)i64_dupe),
-              "Integer64 Mimic");
-    DECREF(i64_dupe);
-    DECREF(i32_dupe);
-    DECREF(f64_dupe);
-    DECREF(f32_dupe);
-    DECREF(i64);
-    DECREF(i32);
-    DECREF(f64);
-    DECREF(f32);
-}
-
-static void
-test_serialization(TestBatch *batch) {
-    Float32   *f32 = Float32_new(1.33f);
-    Float64   *f64 = Float64_new(1.33);
-    Integer32 *i32 = Int32_new(-1);
-    Integer64 *i64 = Int64_new(-1);
-    Float32   *f32_thaw = (Float32*)TestUtils_freeze_thaw((Obj*)f32);
-    Float64   *f64_thaw = (Float64*)TestUtils_freeze_thaw((Obj*)f64);
-    Integer32 *i32_thaw = (Integer32*)TestUtils_freeze_thaw((Obj*)i32);
-    Integer64 *i64_thaw = (Integer64*)TestUtils_freeze_thaw((Obj*)i64);
-    BoolNum   *true_thaw = (BoolNum*)TestUtils_freeze_thaw((Obj*)CFISH_TRUE);
-
-    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f32_thaw),
-              "Float32 freeze/thaw");
-    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f64_thaw),
-              "Float64 freeze/thaw");
-    TEST_TRUE(batch, Int32_Equals(i32, (Obj*)i32_thaw),
-              "Integer32 freeze/thaw");
-    TEST_TRUE(batch, Int64_Equals(i64, (Obj*)i64_thaw),
-              "Integer64 freeze/thaw");
-    TEST_TRUE(batch, Bool_Equals(CFISH_TRUE, (Obj*)true_thaw),
-              "BoolNum freeze/thaw");
-
-    DECREF(i64_thaw);
-    DECREF(i32_thaw);
-    DECREF(f64_thaw);
-    DECREF(f32_thaw);
-    DECREF(i64);
-    DECREF(i32);
-    DECREF(f64);
-    DECREF(f32);
-}
-
-void
-TestNum_run_tests(TestNum *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_To_String(batch);
-    test_accessors(batch);
-    test_Equals_and_Compare_To(batch);
-    test_Clone(batch);
-    test_Mimic(batch);
-    test_serialization(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestNum.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestNum.cfh b/core/Lucy/Test/Object/TestNum.cfh
deleted file mode 100644
index 231571e..0000000
--- a/core/Lucy/Test/Object/TestNum.cfh
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Object::TestNum
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestNum*
-    new(TestFormatter *formatter);
-
-    inert TestNum*
-    init(TestNum *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestNum *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestObj.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestObj.c b/core/Lucy/Test/Object/TestObj.c
deleted file mode 100644
index 1cd137b..0000000
--- a/core/Lucy/Test/Object/TestObj.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-
-#define C_LUCY_TESTOBJ
-#include "Lucy/Util/ToolSet.h"
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/Object/TestObj.h"
-
-TestObj*
-TestObj_new(TestFormatter *formatter) {
-    TestObj *self = (TestObj*)VTable_Make_Obj(TESTOBJ);
-    return TestObj_init(self, formatter);
-}
-
-TestObj*
-TestObj_init(TestObj *self, TestFormatter *formatter) {
-    return (TestObj*)TestBatch_init((TestBatch*)self, 20, formatter);
-}
-
-static Obj*
-S_new_testobj() {
-    ZombieCharBuf *klass = ZCB_WRAP_STR("TestObj", 7);
-    Obj *obj;
-    VTable *vtable = VTable_fetch_vtable((CharBuf*)klass);
-    if (!vtable) {
-        vtable = VTable_singleton((CharBuf*)klass, OBJ);
-    }
-    obj = VTable_Make_Obj(vtable);
-    return Obj_init(obj);
-}
-
-static void
-test_refcounts(TestBatch *batch) {
-    Obj *obj = S_new_testobj();
-
-    TEST_INT_EQ(batch, Obj_Get_RefCount(obj), 1,
-                "Correct starting refcount");
-
-    Obj_Inc_RefCount(obj);
-    TEST_INT_EQ(batch, Obj_Get_RefCount(obj), 2, "Inc_RefCount");
-
-    Obj_Dec_RefCount(obj);
-    TEST_INT_EQ(batch, Obj_Get_RefCount(obj), 1, "Dec_RefCount");
-
-    DECREF(obj);
-}
-
-static void
-test_To_String(TestBatch *batch) {
-    Obj *testobj = S_new_testobj();
-    CharBuf *string = Obj_To_String(testobj);
-    ZombieCharBuf *temp = ZCB_WRAP(string);
-    while (ZCB_Get_Size(temp)) {
-        if (ZCB_Starts_With_Str(temp, "TestObj", 7)) { break; }
-        ZCB_Nip_One(temp);
-    }
-    TEST_TRUE(batch, ZCB_Starts_With_Str(temp, "TestObj", 7), "To_String");
-    DECREF(string);
-    DECREF(testobj);
-}
-
-static void
-test_Dump(TestBatch *batch) {
-    Obj *testobj = S_new_testobj();
-    CharBuf *string = Obj_To_String(testobj);
-    Obj *dump = Obj_Dump(testobj);
-    TEST_TRUE(batch, Obj_Equals(dump, (Obj*)string),
-              "Default Dump returns To_String");
-    DECREF(dump);
-    DECREF(string);
-    DECREF(testobj);
-}
-
-static void
-test_Equals(TestBatch *batch) {
-    Obj *testobj = S_new_testobj();
-    Obj *other   = S_new_testobj();
-
-    TEST_TRUE(batch, Obj_Equals(testobj, testobj),
-              "Equals is true for the same object");
-    TEST_FALSE(batch, Obj_Equals(testobj, other),
-               "Distinct objects are not equal");
-
-    DECREF(testobj);
-    DECREF(other);
-}
-
-static void
-test_Hash_Sum(TestBatch *batch) {
-    Obj *testobj = S_new_testobj();
-    int64_t address64 = PTR_TO_I64(testobj);
-    int32_t address32 = (int32_t)address64;
-    TEST_TRUE(batch, (Obj_Hash_Sum(testobj) == address32),
-              "Hash_Sum uses memory address");
-    DECREF(testobj);
-}
-
-static void
-test_Is_A(TestBatch *batch) {
-    CharBuf *charbuf   = CB_new(0);
-    VTable  *bb_vtable = CB_Get_VTable(charbuf);
-    CharBuf *klass     = CB_Get_Class_Name(charbuf);
-
-    TEST_TRUE(batch, CB_Is_A(charbuf, CHARBUF), "CharBuf Is_A CharBuf.");
-    TEST_TRUE(batch, CB_Is_A(charbuf, OBJ), "CharBuf Is_A Obj.");
-    TEST_TRUE(batch, bb_vtable == CHARBUF, "Get_VTable");
-    TEST_TRUE(batch, CB_Equals(VTable_Get_Name(CHARBUF), (Obj*)klass),
-              "Get_Class_Name");
-
-    DECREF(charbuf);
-}
-
-static void
-S_attempt_init(void *context) {
-    Obj_init((Obj*)context);
-}
-
-static void
-S_attempt_Clone(void *context) {
-    Obj_Clone((Obj*)context);
-}
-
-static void
-S_attempt_Make(void *context) {
-    Obj_Make((Obj*)context);
-}
-
-static void
-S_attempt_Compare_To(void *context) {
-    Obj_Compare_To((Obj*)context, (Obj*)context);
-}
-
-static void
-S_attempt_To_I64(void *context) {
-    Obj_To_I64((Obj*)context);
-}
-
-static void
-S_attempt_To_F64(void *context) {
-    Obj_To_F64((Obj*)context);
-}
-
-static void
-S_attempt_Load(void *context) {
-    Obj_Load((Obj*)context, (Obj*)context);
-}
-
-static void
-S_attempt_Mimic(void *context) {
-    Obj_Mimic((Obj*)context, (Obj*)context);
-}
-
-static void
-S_verify_abstract_error(TestBatch *batch, Err_Attempt_t routine,
-                        void *context, const char *name) {
-    char message[100];
-    sprintf(message, "%s() is abstract", name);
-    Err *error = Err_trap(routine, context);
-    TEST_TRUE(batch, error != NULL
-              && Err_Is_A(error, ERR) 
-              && CB_Find_Str(Err_Get_Mess(error), "bstract", 7) != -1,
-              message);
-    DECREF(error);
-}
-
-static void
-test_abstract_routines(TestBatch *batch) {
-    Obj *blank = VTable_Make_Obj(OBJ);
-    S_verify_abstract_error(batch, S_attempt_init, blank, "init");
-
-    Obj *obj = S_new_testobj();
-    S_verify_abstract_error(batch, S_attempt_Clone,      obj, "Clone");
-    S_verify_abstract_error(batch, S_attempt_Make,       obj, "Make");
-    S_verify_abstract_error(batch, S_attempt_Compare_To, obj, "Compare_To");
-    S_verify_abstract_error(batch, S_attempt_To_I64,     obj, "To_I64");
-    S_verify_abstract_error(batch, S_attempt_To_F64,     obj, "To_F64");
-    S_verify_abstract_error(batch, S_attempt_Load,       obj, "Load");
-    S_verify_abstract_error(batch, S_attempt_Mimic,      obj, "Mimic");
-    DECREF(obj);
-}
-
-void
-TestObj_run_tests(TestObj *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_refcounts(batch);
-    test_To_String(batch);
-    test_Dump(batch);
-    test_Equals(batch);
-    test_Hash_Sum(batch);
-    test_Is_A(batch);
-    test_abstract_routines(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestObj.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestObj.cfh b/core/Lucy/Test/Object/TestObj.cfh
deleted file mode 100644
index f1c5114..0000000
--- a/core/Lucy/Test/Object/TestObj.cfh
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Object::TestObj
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestObj*
-    new(TestFormatter *formatter);
-
-    inert TestObj*
-    init(TestObj *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestObj *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestVArray.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestVArray.c b/core/Lucy/Test/Object/TestVArray.c
deleted file mode 100644
index ef28162..0000000
--- a/core/Lucy/Test/Object/TestVArray.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_LUCY_TESTVARRAY
-#include "Lucy/Util/ToolSet.h"
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/TestUtils.h"
-#include "Lucy/Test/Object/TestVArray.h"
-
-TestVArray*
-TestVArray_new(TestFormatter *formatter) {
-    TestVArray *self = (TestVArray*)VTable_Make_Obj(TESTVARRAY);
-    return TestVArray_init(self, formatter);
-}
-
-TestVArray*
-TestVArray_init(TestVArray *self, TestFormatter *formatter) {
-    return (TestVArray*)TestBatch_init((TestBatch*)self, 45, formatter);
-}
-
-static CharBuf*
-S_new_cb(const char *text) {
-    return CB_new_from_utf8(text, strlen(text));
-}
-
-static void
-test_Equals(TestBatch *batch) {
-    VArray *array = VA_new(0);
-    VArray *other = VA_new(0);
-    ZombieCharBuf *stuff = ZCB_WRAP_STR("stuff", 5);
-
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)other),
-              "Empty arrays are equal");
-
-    VA_Push(array, (Obj*)CFISH_TRUE);
-    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
-               "Add one elem and Equals returns false");
-
-    VA_Push(other, (Obj*)CFISH_TRUE);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)other),
-              "Add a matching elem and Equals returns true");
-
-    VA_Store(array, 2, (Obj*)CFISH_TRUE);
-    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
-               "Add elem after a NULL and Equals returns false");
-
-    VA_Store(other, 2, (Obj*)CFISH_TRUE);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)other),
-              "Empty elems don't spoil Equals");
-
-    VA_Store(other, 2, INCREF(stuff));
-    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
-               "Non-matching value spoils Equals");
-
-    VA_Excise(array, 1, 2); // removes empty elems
-    VA_Delete(other, 1);    // leaves NULL in place of deleted elem
-    VA_Delete(other, 2);
-    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
-               "Empty trailing elements spoil Equals");
-
-    DECREF(array);
-    DECREF(other);
-}
-
-static void
-test_Store_Fetch(TestBatch *batch) {
-    VArray *array = VA_new(0);
-    CharBuf *elem;
-
-    TEST_TRUE(batch, VA_Fetch(array, 2) == NULL, "Fetch beyond end");
-
-    VA_Store(array, 2, (Obj*)CB_newf("foo"));
-    elem = (CharBuf*)CERTIFY(VA_Fetch(array, 2), CHARBUF);
-    TEST_INT_EQ(batch, 3, VA_Get_Size(array), "Store updates size");
-    TEST_TRUE(batch, CB_Equals_Str(elem, "foo", 3), "Store");
-
-    INCREF(elem);
-    TEST_INT_EQ(batch, 2, CB_Get_RefCount(elem),
-                "start with refcount of 2");
-    VA_Store(array, 2, (Obj*)CB_newf("bar"));
-    TEST_INT_EQ(batch, 1, CB_Get_RefCount(elem),
-                "Displacing elem via Store updates refcount");
-    DECREF(elem);
-    elem = (CharBuf*)CERTIFY(VA_Fetch(array, 2), CHARBUF);
-    TEST_TRUE(batch, CB_Equals_Str(elem, "bar", 3), "Store displacement");
-
-    DECREF(array);
-}
-
-static void
-test_Push_Pop_Shift_Unshift(TestBatch *batch) {
-    VArray *array = VA_new(0);
-    CharBuf *elem;
-
-    TEST_INT_EQ(batch, VA_Get_Size(array), 0, "size starts at 0");
-    VA_Push(array, (Obj*)CB_newf("a"));
-    VA_Push(array, (Obj*)CB_newf("b"));
-    VA_Push(array, (Obj*)CB_newf("c"));
-
-    TEST_INT_EQ(batch, VA_Get_Size(array), 3, "size after Push");
-    TEST_TRUE(batch, NULL != CERTIFY(VA_Fetch(array, 2), CHARBUF), "Push");
-
-    elem = (CharBuf*)CERTIFY(VA_Shift(array), CHARBUF);
-    TEST_TRUE(batch, CB_Equals_Str(elem, "a", 1), "Shift");
-    TEST_INT_EQ(batch, VA_Get_Size(array), 2, "size after Shift");
-    DECREF(elem);
-
-    elem = (CharBuf*)CERTIFY(VA_Pop(array), CHARBUF);
-    TEST_TRUE(batch, CB_Equals_Str(elem, "c", 1), "Pop");
-    TEST_INT_EQ(batch, VA_Get_Size(array), 1, "size after Pop");
-    DECREF(elem);
-
-    VA_Unshift(array, (Obj*)CB_newf("foo"));
-    elem = (CharBuf*)CERTIFY(VA_Fetch(array, 0), CHARBUF);
-    TEST_TRUE(batch, CB_Equals_Str(elem, "foo", 3), "Unshift");
-    TEST_INT_EQ(batch, VA_Get_Size(array), 2, "size after Shift");
-
-    DECREF(array);
-}
-
-static void
-test_Delete(TestBatch *batch) {
-    VArray *wanted = VA_new(5);
-    VArray *got    = VA_new(5);
-    uint32_t i;
-
-    for (i = 0; i < 5; i++) { VA_Push(got, (Obj*)CB_newf("%u32", i)); }
-    VA_Store(wanted, 0, (Obj*)CB_newf("0", i));
-    VA_Store(wanted, 1, (Obj*)CB_newf("1", i));
-    VA_Store(wanted, 4, (Obj*)CB_newf("4", i));
-    DECREF(VA_Delete(got, 2));
-    DECREF(VA_Delete(got, 3));
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got), "Delete");
-
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_Resize(TestBatch *batch) {
-    VArray *array = VA_new(3);
-    uint32_t i;
-
-    for (i = 0; i < 2; i++) { VA_Push(array, (Obj*)CB_newf("%u32", i)); }
-    TEST_INT_EQ(batch, VA_Get_Capacity(array), 3, "Start with capacity 3");
-
-    VA_Resize(array, 4);
-    TEST_INT_EQ(batch, VA_Get_Size(array), 4, "Resize up");
-    TEST_INT_EQ(batch, VA_Get_Capacity(array), 4,
-                "Resize changes capacity");
-
-    VA_Resize(array, 2);
-    TEST_INT_EQ(batch, VA_Get_Size(array), 2, "Resize down");
-    TEST_TRUE(batch, VA_Fetch(array, 2) == NULL, "Resize down zaps elem");
-
-    DECREF(array);
-}
-
-static void
-test_Excise(TestBatch *batch) {
-    VArray *wanted = VA_new(5);
-    VArray *got    = VA_new(5);
-
-    for (uint32_t i = 0; i < 5; i++) {
-        VA_Push(wanted, (Obj*)CB_newf("%u32", i));
-        VA_Push(got, (Obj*)CB_newf("%u32", i));
-    }
-
-    VA_Excise(got, 7, 1);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
-              "Excise outside of range is no-op");
-
-    VA_Excise(got, 2, 2);
-    DECREF(VA_Delete(wanted, 2));
-    DECREF(VA_Delete(wanted, 3));
-    VA_Store(wanted, 2, VA_Delete(wanted, 4));
-    VA_Resize(wanted, 3);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
-              "Excise multiple elems");
-
-    VA_Excise(got, 2, 2);
-    VA_Resize(wanted, 2);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
-              "Splicing too many elems truncates");
-
-    VA_Excise(got, 0, 1);
-    VA_Store(wanted, 0, VA_Delete(wanted, 1));
-    VA_Resize(wanted, 1);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
-              "Excise first elem");
-
-    DECREF(got);
-    DECREF(wanted);
-}
-
-static void
-test_Push_VArray(TestBatch *batch) {
-    VArray *wanted  = VA_new(0);
-    VArray *got     = VA_new(0);
-    VArray *scratch = VA_new(0);
-    uint32_t i;
-
-    for (i = 0; i < 4; i++) { VA_Push(wanted, (Obj*)CB_newf("%u32", i)); }
-    for (i = 0; i < 2; i++) { VA_Push(got, (Obj*)CB_newf("%u32", i)); }
-    for (i = 2; i < 4; i++) { VA_Push(scratch, (Obj*)CB_newf("%u32", i)); }
-
-    VA_Push_VArray(got, scratch);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got), "Push_VArray");
-
-    DECREF(wanted);
-    DECREF(got);
-    DECREF(scratch);
-}
-
-static void
-test_Slice(TestBatch *batch) {
-    VArray *array = VA_new(0);
-    for (uint32_t i = 0; i < 10; i++) { VA_Push(array, (Obj*)CB_newf("%u32", i)); }
-    {
-        VArray *slice = VA_Slice(array, 0, 10);
-        TEST_TRUE(batch, VA_Equals(array, (Obj*)slice), "Slice entire array");
-        DECREF(slice);
-    }
-    {
-        VArray *slice = VA_Slice(array, 0, 11);
-        TEST_TRUE(batch, VA_Equals(array, (Obj*)slice),
-            "Exceed length");
-        DECREF(slice);
-    }
-    {
-        VArray *wanted = VA_new(0);
-        VA_Push(wanted, (Obj*)CB_newf("9"));
-        VArray *slice = VA_Slice(array, 9, 11);
-        TEST_TRUE(batch, VA_Equals(slice, (Obj*)wanted),
-            "Exceed length, start near end");
-        DECREF(slice);
-        DECREF(wanted);
-    }
-    {
-        VArray *slice = VA_Slice(array, 0, 0);
-        TEST_TRUE(batch, VA_Get_Size(slice) == 0, "empty slice");
-        DECREF(slice);
-    }
-    {
-        VArray *slice = VA_Slice(array, 20, 1);
-        TEST_TRUE(batch, VA_Get_Size(slice) ==  0, "exceed offset");
-        DECREF(slice);
-    }
-    {
-        VArray *wanted = VA_new(0);
-        VA_Push(wanted, (Obj*)CB_newf("9"));
-        VArray *slice = VA_Slice(array, 9, UINT32_MAX - 1);
-        TEST_TRUE(batch, VA_Get_Size(slice) == 1, "guard against overflow");
-        DECREF(slice);
-        DECREF(wanted);
-    }
-    DECREF(array);
-}
-
-static void
-test_Clone_and_Shallow_Copy(TestBatch *batch) {
-    VArray *array = VA_new(0);
-    VArray *twin;
-    uint32_t i;
-
-    for (i = 0; i < 10; i++) {
-        VA_Push(array, (Obj*)CB_newf("%u32", i));
-    }
-    twin = VA_Shallow_Copy(array);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)twin), "Shallow_Copy");
-    TEST_TRUE(batch, VA_Fetch(array, 1) == VA_Fetch(twin, 1),
-              "Shallow_Copy doesn't clone elements");
-    DECREF(twin);
-
-    twin = VA_Clone(array);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)twin), "Clone");
-    TEST_TRUE(batch, VA_Fetch(array, 1) != VA_Fetch(twin, 1),
-              "Clone performs deep clone");
-
-    DECREF(array);
-    DECREF(twin);
-}
-
-static void
-test_Dump_and_Load(TestBatch *batch) {
-    VArray *array = VA_new(0);
-    Obj    *dump;
-    VArray *loaded;
-
-    VA_Push(array, (Obj*)S_new_cb("foo"));
-    dump = (Obj*)VA_Dump(array);
-    loaded = (VArray*)Obj_Load(dump, dump);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)loaded),
-              "Dump => Load round trip");
-
-    DECREF(array);
-    DECREF(dump);
-    DECREF(loaded);
-}
-
-static void
-test_serialization(TestBatch *batch) {
-    VArray *array = VA_new(0);
-    VArray *dupe;
-    VA_Store(array, 1, (Obj*)CB_newf("foo"));
-    VA_Store(array, 3, (Obj*)CB_newf("bar"));
-    dupe = (VArray*)TestUtils_freeze_thaw((Obj*)array);
-    TEST_TRUE(batch, dupe && VA_Equals(array, (Obj*)dupe),
-              "Round trip through FREEZE/THAW");
-    DECREF(dupe);
-    DECREF(array);
-}
-
-void
-TestVArray_run_tests(TestVArray *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Equals(batch);
-    test_Store_Fetch(batch);
-    test_Push_Pop_Shift_Unshift(batch);
-    test_Delete(batch);
-    test_Resize(batch);
-    test_Excise(batch);
-    test_Push_VArray(batch);
-    test_Slice(batch);
-    test_Clone_and_Shallow_Copy(batch);
-    test_Dump_and_Load(batch);
-    test_serialization(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestVArray.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestVArray.cfh b/core/Lucy/Test/Object/TestVArray.cfh
deleted file mode 100644
index 14a8e15..0000000
--- a/core/Lucy/Test/Object/TestVArray.cfh
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Object::TestVArray
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestVArray*
-    new(TestFormatter *formatter);
-
-    inert TestVArray*
-    init(TestVArray *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestVArray *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/TestUtils.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestUtils.c b/core/Lucy/Test/TestUtils.c
index d3c41f7..e724694 100644
--- a/core/Lucy/Test/TestUtils.c
+++ b/core/Lucy/Test/TestUtils.c
@@ -78,7 +78,7 @@ TestUtils_random_f64s(double *buf, size_t count) {
     return f64s;
 }
 
-uint32_t
+static uint32_t
 S_random_code_point(void) {
     uint32_t code_point = 0;
     while (1) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Util/TestAtomic.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestAtomic.c b/core/Lucy/Test/Util/TestAtomic.c
deleted file mode 100644
index c4d8554..0000000
--- a/core/Lucy/Test/Util/TestAtomic.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Lucy/Util/ToolSet.h"
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/Util/TestAtomic.h"
-#include "Clownfish/Util/Atomic.h"
-
-TestAtomic*
-TestAtomic_new(TestFormatter *formatter) {
-    TestAtomic *self = (TestAtomic*)VTable_Make_Obj(TESTATOMIC);
-    return TestAtomic_init(self, formatter);
-}
-
-TestAtomic*
-TestAtomic_init(TestAtomic *self, TestFormatter *formatter) {
-    return (TestAtomic*)TestBatch_init((TestBatch*)self, 6, formatter);
-}
-
-static void
-test_cas_ptr(TestBatch *batch) {
-    int    foo = 1;
-    int    bar = 2;
-    int   *foo_pointer = &foo;
-    int   *bar_pointer = &bar;
-    int   *target      = NULL;
-
-    TEST_TRUE(batch,
-              Atomic_cas_ptr((void**)&target, NULL, foo_pointer),
-              "cas_ptr returns true on success");
-    TEST_TRUE(batch, target == foo_pointer, "cas_ptr sets target");
-
-    target = NULL;
-    TEST_FALSE(batch,
-               Atomic_cas_ptr((void**)&target, bar_pointer, foo_pointer),
-               "cas_ptr returns false when it old_value doesn't match");
-    TEST_TRUE(batch, target == NULL,
-              "cas_ptr doesn't do anything to target when old_value doesn't match");
-
-    target = foo_pointer;
-    TEST_TRUE(batch,
-              Atomic_cas_ptr((void**)&target, foo_pointer, bar_pointer),
-              "cas_ptr from one value to another");
-    TEST_TRUE(batch, target == bar_pointer, "cas_ptr sets target");
-}
-
-void
-TestAtomic_run_tests(TestAtomic *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_cas_ptr(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Util/TestAtomic.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestAtomic.cfh b/core/Lucy/Test/Util/TestAtomic.cfh
deleted file mode 100644
index fc7060c..0000000
--- a/core/Lucy/Test/Util/TestAtomic.cfh
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Util::TestAtomic
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestAtomic*
-    new(TestFormatter *formatter);
-
-    inert TestAtomic*
-    init(TestAtomic *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestAtomic *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Util/TestMemory.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestMemory.c b/core/Lucy/Test/Util/TestMemory.c
deleted file mode 100644
index 429c6bc..0000000
--- a/core/Lucy/Test/Util/TestMemory.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_LUCY_TESTMEMORYPOOL
-#define C_LUCY_MEMORYPOOL
-#include "Lucy/Util/ToolSet.h"
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/Util/TestMemory.h"
-
-TestMemory*
-TestMemory_new(TestFormatter *formatter) {
-    TestMemory *self = (TestMemory*)VTable_Make_Obj(TESTMEMORY);
-    return TestMemory_init(self, formatter);
-}
-
-TestMemory*
-TestMemory_init(TestMemory *self, TestFormatter *formatter) {
-    return (TestMemory*)TestBatch_init((TestBatch*)self, 30, formatter);
-}
-
-static void
-test_oversize__growth_rate(TestBatch *batch) {
-    bool     success             = true;
-    uint64_t size                = 0;
-    double   growth_count        = 0;
-    double   average_growth_rate = 0.0;
-
-    while (size < SIZE_MAX) {
-        uint64_t next_size = Memory_oversize((size_t)size + 1, sizeof(void*));
-        if (next_size < size) {
-            success = false;
-            FAIL(batch, "Asked for %" PRId64 ", got smaller amount %" PRId64,
-                 size + 1, next_size);
-            break;
-        }
-        if (size > 0) {
-            growth_count += 1;
-            double growth_rate = U64_TO_DOUBLE(next_size) /
-                                 U64_TO_DOUBLE(size);
-            double sum = growth_rate + (growth_count - 1) * average_growth_rate;
-            average_growth_rate = sum / growth_count;
-            if (average_growth_rate < 1.1) {
-                FAIL(batch, "Average growth rate dropped below 1.1x: %f",
-                     average_growth_rate);
-                success = false;
-                break;
-            }
-        }
-        size = next_size;
-    }
-    TEST_TRUE(batch, growth_count > 0, "Grew %f times", growth_count);
-    if (success) {
-        TEST_TRUE(batch, average_growth_rate > 1.1,
-                  "Growth rate of oversize() averages above 1.1: %.3f",
-                  average_growth_rate);
-    }
-
-    for (int minimum = 1; minimum < 8; minimum++) {
-        uint64_t next_size = Memory_oversize(minimum, sizeof(void*));
-        double growth_rate = U64_TO_DOUBLE(next_size) / (double)minimum;
-        TEST_TRUE(batch, growth_rate > 1.2,
-                  "Growth rate is higher for smaller arrays (%d, %.3f)", minimum,
-                  growth_rate);
-    }
-}
-
-static void
-test_oversize__ceiling(TestBatch *batch) {
-    for (int width = 0; width < 10; width++) {
-        size_t size = Memory_oversize(SIZE_MAX, width);
-        TEST_TRUE(batch, size == SIZE_MAX,
-                  "Memory_oversize hits ceiling at SIZE_MAX (width %d)", width);
-        size = Memory_oversize(SIZE_MAX - 1, width);
-        TEST_TRUE(batch, size == SIZE_MAX,
-                  "Memory_oversize hits ceiling at SIZE_MAX (width %d)", width);
-    }
-}
-
-static void
-test_oversize__rounding(TestBatch *batch) {
-    int widths[] = { 1, 2, 4, 0 };
-
-    for (int width_tick = 0; widths[width_tick] != 0; width_tick++) {
-        int width = widths[width_tick];
-        for (int i = 0; i < 25; i++) {
-            size_t size = Memory_oversize(i, width);
-            size_t bytes = size * width;
-            if (bytes % sizeof(void*) != 0) {
-                FAIL(batch, "Rounding failure for %d, width %d",
-                     i, width);
-                return;
-            }
-        }
-    }
-    PASS(batch, "Round allocations up to the size of a pointer");
-}
-
-void
-TestMemory_run_tests(TestMemory *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_oversize__growth_rate(batch);
-    test_oversize__ceiling(batch);
-    test_oversize__rounding(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Util/TestMemory.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestMemory.cfh b/core/Lucy/Test/Util/TestMemory.cfh
deleted file mode 100644
index 9b95716..0000000
--- a/core/Lucy/Test/Util/TestMemory.cfh
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Util::TestMemory
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestMemory*
-    new(TestFormatter *formatter);
-
-    inert TestMemory*
-    init(TestMemory *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestMemory *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Util/TestNumberUtils.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestNumberUtils.c b/core/Lucy/Test/Util/TestNumberUtils.c
deleted file mode 100644
index fecab9a..0000000
--- a/core/Lucy/Test/Util/TestNumberUtils.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_LUCY_TESTNUMBERUTILS
-#include "Lucy/Util/ToolSet.h"
-#include <stdlib.h>
-#include <time.h>
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/TestUtils.h"
-#include "Lucy/Test/Util/TestNumberUtils.h"
-#include "Clownfish/Util/NumberUtils.h"
-
-TestNumberUtils*
-TestNumUtil_new(TestFormatter *formatter) {
-    TestNumberUtils *self = (TestNumberUtils*)VTable_Make_Obj(TESTNUMBERUTILS);
-    return TestNumUtil_init(self, formatter);
-}
-
-TestNumberUtils*
-TestNumUtil_init(TestNumberUtils *self, TestFormatter *formatter) {
-    return (TestNumberUtils*)TestBatch_init((TestBatch*)self, 1196, formatter);
-}
-
-static void
-test_u1(TestBatch *batch) {
-    size_t    count   = 64;
-    uint64_t *ints    = TestUtils_random_u64s(NULL, count, 0, 2);
-    size_t    amount  = count / 8;
-    uint8_t  *bits    = (uint8_t*)CALLOCATE(amount, sizeof(uint8_t));
-
-    for (size_t i = 0; i < count; i++) {
-        if (ints[i]) { NumUtil_u1set(bits, i); }
-    }
-    for (size_t i = 0; i < count; i++) {
-        TEST_INT_EQ(batch, NumUtil_u1get(bits, i), (long)ints[i],
-                    "u1 set/get");
-    }
-
-    for (size_t i = 0; i < count; i++) {
-        NumUtil_u1flip(bits, i);
-    }
-    for (size_t i = 0; i < count; i++) {
-        TEST_INT_EQ(batch, NumUtil_u1get(bits, i), !ints[i], "u1 flip");
-    }
-
-    FREEMEM(bits);
-    FREEMEM(ints);
-}
-
-static void
-test_u2(TestBatch *batch) {
-    size_t    count = 32;
-    uint64_t *ints = TestUtils_random_u64s(NULL, count, 0, 4);
-    uint8_t  *bits = (uint8_t*)CALLOCATE((count / 4), sizeof(uint8_t));
-
-    for (size_t i = 0; i < count; i++) {
-        NumUtil_u2set(bits, i, (uint8_t)ints[i]);
-    }
-    for (size_t i = 0; i < count; i++) {
-        TEST_INT_EQ(batch, NumUtil_u2get(bits, i), (long)ints[i], "u2");
-    }
-
-    FREEMEM(bits);
-    FREEMEM(ints);
-}
-
-static void
-test_u4(TestBatch *batch) {
-    size_t    count = 128;
-    uint64_t *ints  = TestUtils_random_u64s(NULL, count, 0, 16);
-    uint8_t  *bits  = (uint8_t*)CALLOCATE((count / 2), sizeof(uint8_t));
-
-    for (size_t i = 0; i < count; i++) {
-        NumUtil_u4set(bits, i, (uint8_t)ints[i]);
-    }
-    for (size_t i = 0; i < count; i++) {
-        TEST_INT_EQ(batch, NumUtil_u4get(bits, i), (long)ints[i], "u4");
-    }
-
-    FREEMEM(bits);
-    FREEMEM(ints);
-}
-
-static void
-test_c32(TestBatch *batch) {
-    uint64_t  mins[]   = { 0,   0x4000 - 100, (uint32_t)INT32_MAX - 100, UINT32_MAX - 10 };
-    uint64_t  limits[] = { 500, 0x4000 + 100, (uint32_t)INT32_MAX + 100, UINT32_MAX      };
-    uint32_t  set_num;
-    uint32_t  num_sets  = sizeof(mins) / sizeof(uint64_t);
-    size_t    count     = 64;
-    uint64_t *ints      = NULL;
-    size_t    amount    = count * C32_MAX_BYTES;
-    char     *encoded   = (char*)CALLOCATE(amount, sizeof(char));
-    char     *target    = encoded;
-    char     *limit     = target + amount;
-
-    for (set_num = 0; set_num < num_sets; set_num++) {
-        char *skip;
-        ints = TestUtils_random_u64s(ints, count,
-                                     mins[set_num], limits[set_num]);
-        target = encoded;
-        for (size_t i = 0; i < count; i++) {
-            NumUtil_encode_c32((uint32_t)ints[i], &target);
-        }
-        target = encoded;
-        skip   = encoded;
-        for (size_t i = 0; i < count; i++) {
-            TEST_INT_EQ(batch, NumUtil_decode_c32(&target), (long)ints[i],
-                        "c32 %lu", (long)ints[i]);
-            NumUtil_skip_cint(&skip);
-            if (target > limit) { THROW(ERR, "overrun"); }
-        }
-        TEST_TRUE(batch, skip == target, "skip %lu == %lu",
-                  (unsigned long)skip, (unsigned long)target);
-
-        target = encoded;
-        for (size_t i = 0; i < count; i++) {
-            NumUtil_encode_padded_c32((uint32_t)ints[i], &target);
-        }
-        TEST_TRUE(batch, target == limit,
-                  "padded c32 uses 5 bytes (%lu == %lu)", (unsigned long)target,
-                  (unsigned long)limit);
-        target = encoded;
-        skip   = encoded;
-        for (size_t i = 0; i < count; i++) {
-            TEST_INT_EQ(batch, NumUtil_decode_c32(&target), (long)ints[i],
-                        "padded c32 %lu", (long)ints[i]);
-            NumUtil_skip_cint(&skip);
-            if (target > limit) { THROW(ERR, "overrun"); }
-        }
-        TEST_TRUE(batch, skip == target, "skip padded %lu == %lu",
-                  (unsigned long)skip, (unsigned long)target);
-    }
-
-    target = encoded;
-    NumUtil_encode_c32(UINT32_MAX, &target);
-    target = encoded;
-    TEST_INT_EQ(batch, NumUtil_decode_c32(&target), UINT32_MAX, "c32 UINT32_MAX");
-
-    FREEMEM(encoded);
-    FREEMEM(ints);
-}
-
-static void
-test_c64(TestBatch *batch) {
-    uint64_t  mins[]    = { 0,   0x4000 - 100, (uint64_t)UINT32_MAX - 100,  UINT64_MAX - 10 };
-    uint64_t  limits[]  = { 500, 0x4000 + 100, (uint64_t)UINT32_MAX + 1000, UINT64_MAX      };
-    uint32_t  set_num;
-    uint32_t  num_sets  = sizeof(mins) / sizeof(uint64_t);
-    size_t    count     = 64;
-    uint64_t *ints      = NULL;
-    size_t    amount    = count * C64_MAX_BYTES;
-    char     *encoded   = (char*)CALLOCATE(amount, sizeof(char));
-    char     *target    = encoded;
-    char     *limit     = target + amount;
-
-    for (set_num = 0; set_num < num_sets; set_num++) {
-        char *skip;
-        ints = TestUtils_random_u64s(ints, count,
-                                     mins[set_num], limits[set_num]);
-        target = encoded;
-        for (size_t i = 0; i < count; i++) {
-            NumUtil_encode_c64(ints[i], &target);
-        }
-        target = encoded;
-        skip   = encoded;
-        for (size_t i = 0; i < count; i++) {
-            uint64_t got = NumUtil_decode_c64(&target);
-            TEST_TRUE(batch, got == ints[i],
-                      "c64 %" PRIu64 " == %" PRIu64, got, ints[i]);
-            if (target > limit) { THROW(ERR, "overrun"); }
-            NumUtil_skip_cint(&skip);
-        }
-        TEST_TRUE(batch, skip == target, "skip %lu == %lu",
-                  (unsigned long)skip, (unsigned long)target);
-    }
-
-    target = encoded;
-    NumUtil_encode_c64(UINT64_MAX, &target);
-    target = encoded;
-
-    uint64_t got = NumUtil_decode_c64(&target);
-    TEST_TRUE(batch, got == UINT64_MAX, "c64 UINT64_MAX");
-
-    FREEMEM(encoded);
-    FREEMEM(ints);
-}
-
-static void
-test_bigend_u16(TestBatch *batch) {
-    size_t    count     = 32;
-    uint64_t *ints      = TestUtils_random_u64s(NULL, count, 0, UINT16_MAX + 1);
-    size_t    amount    = (count + 1) * sizeof(uint16_t);
-    char     *allocated = (char*)CALLOCATE(amount, sizeof(char));
-    char     *encoded   = allocated + 1; // Intentionally misaligned.
-    char     *target    = encoded;
-
-    for (size_t i = 0; i < count; i++) {
-        NumUtil_encode_bigend_u16((uint16_t)ints[i], &target);
-        target += sizeof(uint16_t);
-    }
-    target = encoded;
-    for (size_t i = 0; i < count; i++) {
-        uint16_t got = NumUtil_decode_bigend_u16(target);
-        TEST_INT_EQ(batch, got, (long)ints[i], "bigend u16");
-        target += sizeof(uint16_t);
-    }
-
-    target = encoded;
-    NumUtil_encode_bigend_u16(1, &target);
-    TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian u16");
-    TEST_INT_EQ(batch, encoded[1], 1, "Truly big-endian u16");
-
-    FREEMEM(allocated);
-    FREEMEM(ints);
-}
-
-static void
-test_bigend_u32(TestBatch *batch) {
-    size_t    count     = 32;
-    uint64_t *ints      = TestUtils_random_u64s(NULL, count, 0, UINT64_C(1) + UINT32_MAX);
-    size_t    amount    = (count + 1) * sizeof(uint32_t);
-    char     *allocated = (char*)CALLOCATE(amount, sizeof(char));
-    char     *encoded   = allocated + 1; // Intentionally misaligned.
-    char     *target    = encoded;
-
-    for (size_t i = 0; i < count; i++) {
-        NumUtil_encode_bigend_u32((uint32_t)ints[i], &target);
-        target += sizeof(uint32_t);
-    }
-    target = encoded;
-    for (size_t i = 0; i < count; i++) {
-        uint32_t got = NumUtil_decode_bigend_u32(target);
-        TEST_INT_EQ(batch, got, (long)ints[i], "bigend u32");
-        target += sizeof(uint32_t);
-    }
-
-    target = encoded;
-    NumUtil_encode_bigend_u32(1, &target);
-    TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian u32");
-    TEST_INT_EQ(batch, encoded[3], 1, "Truly big-endian u32");
-
-    FREEMEM(allocated);
-    FREEMEM(ints);
-}
-
-static void
-test_bigend_u64(TestBatch *batch) {
-    size_t    count     = 32;
-    uint64_t *ints      = TestUtils_random_u64s(NULL, count, 0, UINT64_MAX);
-    size_t    amount    = (count + 1) * sizeof(uint64_t);
-    char     *allocated = (char*)CALLOCATE(amount, sizeof(char));
-    char     *encoded   = allocated + 1; // Intentionally misaligned.
-    char     *target    = encoded;
-
-    for (size_t i = 0; i < count; i++) {
-        NumUtil_encode_bigend_u64(ints[i], &target);
-        target += sizeof(uint64_t);
-    }
-    target = encoded;
-    for (size_t i = 0; i < count; i++) {
-        uint64_t got = NumUtil_decode_bigend_u64(target);
-        TEST_TRUE(batch, got == ints[i], "bigend u64");
-        target += sizeof(uint64_t);
-    }
-
-    target = encoded;
-    NumUtil_encode_bigend_u64(1, &target);
-    TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian");
-    TEST_INT_EQ(batch, encoded[7], 1, "Truly big-endian");
-
-    FREEMEM(allocated);
-    FREEMEM(ints);
-}
-
-static void
-test_bigend_f32(TestBatch *batch) {
-    float    source[]  = { -1.3f, 0.0f, 100.2f };
-    size_t   count     = 3;
-    size_t   amount    = (count + 1) * sizeof(float);
-    uint8_t *allocated = (uint8_t*)CALLOCATE(amount, sizeof(uint8_t));
-    uint8_t *encoded   = allocated + 1; // Intentionally misaligned.
-    uint8_t *target    = encoded;
-
-    for (size_t i = 0; i < count; i++) {
-        NumUtil_encode_bigend_f32(source[i], &target);
-        target += sizeof(float);
-    }
-    target = encoded;
-    for (size_t i = 0; i < count; i++) {
-        float got = NumUtil_decode_bigend_f32(target);
-        TEST_TRUE(batch, got == source[i], "bigend f32");
-        target += sizeof(float);
-    }
-
-    target = encoded;
-    NumUtil_encode_bigend_f32(-2.0f, &target);
-    TEST_INT_EQ(batch, (encoded[0] & 0x80), 0x80,
-                "Truly big-endian (IEEE 754 sign bit set for negative number)");
-    TEST_INT_EQ(batch, encoded[0], 0xC0,
-                "IEEE 754 representation of -2.0f, byte 0");
-    for (size_t i = 1; i < sizeof(float); i++) {
-        TEST_INT_EQ(batch, encoded[i], 0,
-                    "IEEE 754 representation of -2.0f, byte %d", (int)i);
-    }
-
-    FREEMEM(allocated);
-}
-
-static void
-test_bigend_f64(TestBatch *batch) {
-    double   source[]  = { -1.3, 0.0, 100.2 };
-    size_t   count     = 3;
-    size_t   amount    = (count + 1) * sizeof(double);
-    uint8_t *allocated = (uint8_t*)CALLOCATE(amount, sizeof(uint8_t));
-    uint8_t *encoded   = allocated + 1; // Intentionally misaligned.
-    uint8_t *target    = encoded;
-
-    for (size_t i = 0; i < count; i++) {
-        NumUtil_encode_bigend_f64(source[i], &target);
-        target += sizeof(double);
-    }
-    target = encoded;
-    for (size_t i = 0; i < count; i++) {
-        double got = NumUtil_decode_bigend_f64(target);
-        TEST_TRUE(batch, got == source[i], "bigend f64");
-        target += sizeof(double);
-    }
-
-    target = encoded;
-    NumUtil_encode_bigend_f64(-2.0, &target);
-    TEST_INT_EQ(batch, (encoded[0] & 0x80), 0x80,
-                "Truly big-endian (IEEE 754 sign bit set for negative number)");
-    TEST_INT_EQ(batch, encoded[0], 0xC0,
-                "IEEE 754 representation of -2.0, byte 0");
-    for (size_t i = 1; i < sizeof(double); i++) {
-        TEST_INT_EQ(batch, encoded[i], 0,
-                    "IEEE 754 representation of -2.0, byte %d", (int)i);
-    }
-
-    FREEMEM(allocated);
-}
-
-void
-TestNumUtil_run_tests(TestNumberUtils *self) {
-    TestBatch *batch = (TestBatch*)self;
-    srand((unsigned int)time((time_t*)NULL));
-    test_u1(batch);
-    test_u2(batch);
-    test_u4(batch);
-    test_c32(batch);
-    test_c64(batch);
-    test_bigend_u16(batch);
-    test_bigend_u32(batch);
-    test_bigend_u64(batch);
-    test_bigend_f32(batch);
-    test_bigend_f64(batch);
-}
-
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Util/TestNumberUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestNumberUtils.cfh b/core/Lucy/Test/Util/TestNumberUtils.cfh
deleted file mode 100644
index 0c5236d..0000000
--- a/core/Lucy/Test/Util/TestNumberUtils.cfh
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Util::TestNumberUtils cnick TestNumUtil
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestNumberUtils*
-    new(TestFormatter *formatter);
-
-    inert TestNumberUtils*
-    init(TestNumberUtils *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestNumberUtils *self);
-}
-
-


[lucy-commits] [20/26] Rework Clownfish test harness

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestRAMFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFolder.c b/core/Lucy/Test/Store/TestRAMFolder.c
index 47a69b5..0f01127 100644
--- a/core/Lucy/Test/Store/TestRAMFolder.c
+++ b/core/Lucy/Test/Store/TestRAMFolder.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Store/TestRAMFolder.h"
 #include "Lucy/Store/RAMFolder.h"
@@ -40,14 +40,8 @@ static CharBuf *nope          = NULL;
 static CharBuf *nope_nyet     = NULL;
 
 TestRAMFolder*
-TestRAMFolder_new(TestFormatter *formatter) {
-    TestRAMFolder *self = (TestRAMFolder*)VTable_Make_Obj(TESTRAMFOLDER);
-    return TestRAMFolder_init(self, formatter);
-}
-
-TestRAMFolder*
-TestRAMFolder_init(TestRAMFolder *self, TestFormatter *formatter) {
-    return (TestRAMFolder*)TestBatch_init((TestBatch*)self, 98, formatter);
+TestRAMFolder_new() {
+    return (TestRAMFolder*)VTable_Make_Obj(TESTRAMFOLDER);
 }
 
 static void
@@ -83,52 +77,52 @@ S_destroy_strings(void) {
 }
 
 static void
-test_Initialize_and_Check(TestBatch *batch) {
+test_Initialize_and_Check(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     RAMFolder_Initialize(folder);
-    PASS(batch, "Initialized concludes without incident");
-    TEST_TRUE(batch, RAMFolder_Check(folder), "Check succeeds");
+    PASS(runner, "Initialized concludes without incident");
+    TEST_TRUE(runner, RAMFolder_Check(folder), "Check succeeds");
     DECREF(folder);
 }
 
 static void
-test_Local_Exists(TestBatch *batch) {
+test_Local_Exists(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     FileHandle *fh = RAMFolder_Open_FileHandle(folder, boffo,
                                                FH_CREATE | FH_WRITE_ONLY);
     DECREF(fh);
     RAMFolder_Local_MkDir(folder, foo);
 
-    TEST_TRUE(batch, RAMFolder_Local_Exists(folder, boffo),
+    TEST_TRUE(runner, RAMFolder_Local_Exists(folder, boffo),
               "Local_Exists() returns true for file");
-    TEST_TRUE(batch, RAMFolder_Local_Exists(folder, foo),
+    TEST_TRUE(runner, RAMFolder_Local_Exists(folder, foo),
               "Local_Exists() returns true for dir");
-    TEST_FALSE(batch, RAMFolder_Local_Exists(folder, bar),
+    TEST_FALSE(runner, RAMFolder_Local_Exists(folder, bar),
                "Local_Exists() returns false for non-existent entry");
 
     DECREF(folder);
 }
 
 static void
-test_Local_Is_Directory(TestBatch *batch) {
+test_Local_Is_Directory(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     FileHandle *fh = RAMFolder_Open_FileHandle(folder, boffo,
                                                FH_CREATE | FH_WRITE_ONLY);
     DECREF(fh);
     RAMFolder_Local_MkDir(folder, foo);
 
-    TEST_FALSE(batch, RAMFolder_Local_Is_Directory(folder, boffo),
+    TEST_FALSE(runner, RAMFolder_Local_Is_Directory(folder, boffo),
                "Local_Is_Directory() returns false for file");
-    TEST_TRUE(batch, RAMFolder_Local_Is_Directory(folder, foo),
+    TEST_TRUE(runner, RAMFolder_Local_Is_Directory(folder, foo),
               "Local_Is_Directory() returns true for dir");
-    TEST_FALSE(batch, RAMFolder_Local_Is_Directory(folder, bar),
+    TEST_FALSE(runner, RAMFolder_Local_Is_Directory(folder, bar),
                "Local_Is_Directory() returns false for non-existent entry");
 
     DECREF(folder);
 }
 
 static void
-test_Local_Find_Folder(TestBatch *batch) {
+test_Local_Find_Folder(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     RAMFolder *local;
     FileHandle *fh;
@@ -143,26 +137,26 @@ test_Local_Find_Folder(TestBatch *batch) {
     DECREF(fh);
 
     local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, nope);
-    TEST_TRUE(batch, local == NULL, "Non-existent entry yields NULL");
+    TEST_TRUE(runner, local == NULL, "Non-existent entry yields NULL");
 
     ZombieCharBuf *empty = ZCB_BLANK();
     local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, (CharBuf*)empty);
-    TEST_TRUE(batch, local == NULL, "Empty string yields NULL");
+    TEST_TRUE(runner, local == NULL, "Empty string yields NULL");
 
     local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, foo_bar);
-    TEST_TRUE(batch, local == NULL, "nested folder yields NULL");
+    TEST_TRUE(runner, local == NULL, "nested folder yields NULL");
 
     local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, foo_boffo);
-    TEST_TRUE(batch, local == NULL, "nested file yields NULL");
+    TEST_TRUE(runner, local == NULL, "nested file yields NULL");
 
     local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, boffo);
-    TEST_TRUE(batch, local == NULL, "local file yields NULL");
+    TEST_TRUE(runner, local == NULL, "local file yields NULL");
 
     local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, bar);
-    TEST_TRUE(batch, local == NULL, "name of nested folder yields NULL");
+    TEST_TRUE(runner, local == NULL, "name of nested folder yields NULL");
 
     local = (RAMFolder*)RAMFolder_Local_Find_Folder(folder, foo);
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               local
               && RAMFolder_Is_A(local, RAMFOLDER)
               && CB_Equals_Str(RAMFolder_Get_Path(local), "foo", 3),
@@ -172,20 +166,20 @@ test_Local_Find_Folder(TestBatch *batch) {
 }
 
 static void
-test_Local_MkDir(TestBatch *batch) {
+test_Local_MkDir(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     bool result;
 
     result = RAMFolder_Local_MkDir(folder, foo);
-    TEST_TRUE(batch, result, "Local_MkDir succeeds and returns true");
+    TEST_TRUE(runner, result, "Local_MkDir succeeds and returns true");
 
     Err_set_error(NULL);
     result = RAMFolder_Local_MkDir(folder, foo);
-    TEST_FALSE(batch, result,
+    TEST_FALSE(runner, result,
                "Local_MkDir returns false when a dir already exists");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Local_MkDir sets Err_error when a dir already exists");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo),
               "Existing dir untouched after failed Local_MkDir");
 
     FileHandle *fh = RAMFolder_Open_FileHandle(folder, boffo,
@@ -193,11 +187,11 @@ test_Local_MkDir(TestBatch *batch) {
     DECREF(fh);
     Err_set_error(NULL);
     result = RAMFolder_Local_MkDir(folder, foo);
-    TEST_FALSE(batch, result,
+    TEST_FALSE(runner, result,
                "Local_MkDir returns false when a file already exists");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Local_MkDir sets Err_error when a file already exists");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, boffo) &&
+    TEST_TRUE(runner, RAMFolder_Exists(folder, boffo) &&
               !RAMFolder_Local_Is_Directory(folder, boffo),
               "Existing file untouched after failed Local_MkDir");
 
@@ -205,62 +199,62 @@ test_Local_MkDir(TestBatch *batch) {
 }
 
 static void
-test_Local_Open_Dir(TestBatch *batch) {
+test_Local_Open_Dir(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     DirHandle *dh = RAMFolder_Local_Open_Dir(folder);
-    TEST_TRUE(batch, dh && DH_Is_A(dh, RAMDIRHANDLE),
+    TEST_TRUE(runner, dh && DH_Is_A(dh, RAMDIRHANDLE),
               "Local_Open_Dir returns a RAMDirHandle");
     DECREF(dh);
     DECREF(folder);
 }
 
 static void
-test_Local_Open_FileHandle(TestBatch *batch) {
+test_Local_Open_FileHandle(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     FileHandle *fh;
 
     fh = RAMFolder_Local_Open_FileHandle(folder, boffo,
                                          FH_CREATE | FH_WRITE_ONLY);
-    TEST_TRUE(batch, fh && FH_Is_A(fh, RAMFILEHANDLE),
+    TEST_TRUE(runner, fh && FH_Is_A(fh, RAMFILEHANDLE),
               "opened FileHandle");
     DECREF(fh);
 
     fh = RAMFolder_Local_Open_FileHandle(folder, boffo,
                                          FH_CREATE | FH_WRITE_ONLY);
-    TEST_TRUE(batch, fh && FH_Is_A(fh, RAMFILEHANDLE),
+    TEST_TRUE(runner, fh && FH_Is_A(fh, RAMFILEHANDLE),
               "opened FileHandle for append");
     DECREF(fh);
 
     Err_set_error(NULL);
     fh = RAMFolder_Local_Open_FileHandle(folder, boffo,
                                          FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
-    TEST_TRUE(batch, fh == NULL, "FH_EXLUSIVE flag prevents open");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, fh == NULL, "FH_EXLUSIVE flag prevents open");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "failure due to FH_EXLUSIVE flag sets Err_error");
 
     fh = RAMFolder_Local_Open_FileHandle(folder, boffo, FH_READ_ONLY);
-    TEST_TRUE(batch, fh && FH_Is_A(fh, RAMFILEHANDLE),
+    TEST_TRUE(runner, fh && FH_Is_A(fh, RAMFILEHANDLE),
               "opened FileHandle for reading");
     DECREF(fh);
 
     Err_set_error(NULL);
     fh = RAMFolder_Local_Open_FileHandle(folder, nope, FH_READ_ONLY);
-    TEST_TRUE(batch, fh == NULL,
+    TEST_TRUE(runner, fh == NULL,
               "Can't open non-existent file for reading");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Opening non-existent file for reading sets Err_error");
 
     DECREF(folder);
 }
 
 static void
-test_Local_Delete(TestBatch *batch) {
+test_Local_Delete(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     FileHandle *fh;
 
     fh = RAMFolder_Open_FileHandle(folder, boffo, FH_CREATE | FH_WRITE_ONLY);
     DECREF(fh);
-    TEST_TRUE(batch, RAMFolder_Local_Delete(folder, boffo),
+    TEST_TRUE(runner, RAMFolder_Local_Delete(folder, boffo),
               "Local_Delete on file succeeds");
 
     RAMFolder_Local_MkDir(folder, foo);
@@ -269,18 +263,18 @@ test_Local_Delete(TestBatch *batch) {
     DECREF(fh);
 
     Err_set_error(NULL);
-    TEST_FALSE(batch, RAMFolder_Local_Delete(folder, foo),
+    TEST_FALSE(runner, RAMFolder_Local_Delete(folder, foo),
                "Local_Delete on non-empty dir fails");
 
     RAMFolder_Delete(folder, foo_boffo);
-    TEST_TRUE(batch, RAMFolder_Local_Delete(folder, foo),
+    TEST_TRUE(runner, RAMFolder_Local_Delete(folder, foo),
               "Local_Delete on empty dir succeeds");
 
     DECREF(folder);
 }
 
 static void
-test_Rename(TestBatch *batch) {
+test_Rename(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     FileHandle *fh;
     bool result;
@@ -293,115 +287,115 @@ test_Rename(TestBatch *batch) {
     // Move files.
 
     result = RAMFolder_Rename(folder, boffo, banana);
-    TEST_TRUE(batch, result, "Rename succeeds and returns true");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, banana),
+    TEST_TRUE(runner, result, "Rename succeeds and returns true");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, banana),
               "File exists at new path");
-    TEST_FALSE(batch, RAMFolder_Exists(folder, boffo),
+    TEST_FALSE(runner, RAMFolder_Exists(folder, boffo),
                "File no longer exists at old path");
 
     result = RAMFolder_Rename(folder, banana, foo_bar_boffo);
-    TEST_TRUE(batch, result, "Rename to file in nested dir");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_bar_boffo),
+    TEST_TRUE(runner, result, "Rename to file in nested dir");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_bar_boffo),
               "File exists at new path");
-    TEST_FALSE(batch, RAMFolder_Exists(folder, banana),
+    TEST_FALSE(runner, RAMFolder_Exists(folder, banana),
                "File no longer exists at old path");
 
     result = RAMFolder_Rename(folder, foo_bar_boffo, boffo);
-    TEST_TRUE(batch, result, "Rename from file in nested dir");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, boffo),
+    TEST_TRUE(runner, result, "Rename from file in nested dir");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, boffo),
               "File exists at new path");
-    TEST_FALSE(batch, RAMFolder_Exists(folder, foo_bar_boffo),
+    TEST_FALSE(runner, RAMFolder_Exists(folder, foo_bar_boffo),
                "File no longer exists at old path");
 
     fh = RAMFolder_Open_FileHandle(folder, foo_boffo,
                                    FH_CREATE | FH_WRITE_ONLY);
     DECREF(fh);
     result = RAMFolder_Rename(folder, boffo, foo_boffo);
-    TEST_TRUE(batch, result, "Clobber");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, result, "Clobber");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "File exists at new path");
-    TEST_FALSE(batch, RAMFolder_Exists(folder, boffo),
+    TEST_FALSE(runner, RAMFolder_Exists(folder, boffo),
                "File no longer exists at old path");
 
     // Move Dirs.
 
     RAMFolder_MkDir(folder, baz);
     result = RAMFolder_Rename(folder, baz, boffo);
-    TEST_TRUE(batch, result, "Rename dir");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, boffo),
+    TEST_TRUE(runner, result, "Rename dir");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, boffo),
               "Folder exists at new path");
-    TEST_FALSE(batch, RAMFolder_Exists(folder, baz),
+    TEST_FALSE(runner, RAMFolder_Exists(folder, baz),
                "Folder no longer exists at old path");
 
     result = RAMFolder_Rename(folder, boffo, foo_foo);
-    TEST_TRUE(batch, result, "Rename dir into nested subdir");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_foo),
+    TEST_TRUE(runner, result, "Rename dir into nested subdir");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_foo),
               "Folder exists at new path");
-    TEST_FALSE(batch, RAMFolder_Exists(folder, boffo),
+    TEST_FALSE(runner, RAMFolder_Exists(folder, boffo),
                "Folder no longer exists at old path");
 
     result = RAMFolder_Rename(folder, foo_foo, foo_bar_baz);
-    TEST_TRUE(batch, result, "Rename dir from nested subdir");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_bar_baz),
+    TEST_TRUE(runner, result, "Rename dir from nested subdir");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_bar_baz),
               "Folder exists at new path");
-    TEST_FALSE(batch, RAMFolder_Exists(folder, foo_foo),
+    TEST_FALSE(runner, RAMFolder_Exists(folder, foo_foo),
                "Folder no longer exists at old path");
 
     // Test failed clobbers.
 
     Err_set_error(NULL);
     result = RAMFolder_Rename(folder, foo_boffo, foo_bar);
-    TEST_FALSE(batch, result, "Rename file clobbering dir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Rename file clobbering dir fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Failed rename sets Err_error");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "File still exists at old path");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_bar),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_bar),
               "Dir still exists after failed clobber");
 
     Err_set_error(NULL);
     result = RAMFolder_Rename(folder, foo_bar, foo_boffo);
-    TEST_FALSE(batch, result, "Rename dir clobbering file fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Rename dir clobbering file fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Failed rename sets Err_error");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_bar),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_bar),
               "Dir still exists at old path");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "File still exists after failed clobber");
 
     // Test that "renaming" succeeds where to and from are the same.
 
     result = RAMFolder_Rename(folder, foo_boffo, foo_boffo);
-    TEST_TRUE(batch, result, "Renaming file to itself succeeds");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, result, "Renaming file to itself succeeds");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "File still exists");
 
     result = RAMFolder_Rename(folder, foo_bar, foo_bar);
-    TEST_TRUE(batch, result, "Renaming dir to itself succeeds");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_bar),
+    TEST_TRUE(runner, result, "Renaming dir to itself succeeds");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_bar),
               "Dir still exists");
 
     // Invalid filepaths.
 
     Err_set_error(NULL);
     result = RAMFolder_Rename(folder, foo_boffo, nope_nyet);
-    TEST_FALSE(batch, result, "Rename into non-existent subdir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Rename into non-existent subdir fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Renaming into non-existent subdir sets Err_error");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "Entry still exists at old path");
 
     Err_set_error(NULL);
     result = RAMFolder_Rename(folder, nope_nyet, boffo);
-    TEST_FALSE(batch, result, "Rename non-existent file fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Rename non-existent file fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Renaming non-existent source file sets Err_error");
 
     DECREF(folder);
 }
 
 static void
-test_Hard_Link(TestBatch *batch) {
+test_Hard_Link(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     FileHandle *fh;
     bool result;
@@ -414,26 +408,26 @@ test_Hard_Link(TestBatch *batch) {
     // Link files.
 
     result = RAMFolder_Hard_Link(folder, boffo, banana);
-    TEST_TRUE(batch, result, "Hard_Link succeeds and returns true");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, banana),
+    TEST_TRUE(runner, result, "Hard_Link succeeds and returns true");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, banana),
               "File exists at new path");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, boffo),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, boffo),
               "File still exists at old path");
     RAMFolder_Delete(folder, boffo);
 
     result = RAMFolder_Hard_Link(folder, banana, foo_bar_boffo);
-    TEST_TRUE(batch, result, "Hard_Link to target within nested dir");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_bar_boffo),
+    TEST_TRUE(runner, result, "Hard_Link to target within nested dir");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_bar_boffo),
               "File exists at new path");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, banana),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, banana),
               "File still exists at old path");
     RAMFolder_Delete(folder, banana);
 
     result = RAMFolder_Hard_Link(folder, foo_bar_boffo, foo_boffo);
-    TEST_TRUE(batch, result, "Hard_Link from file in nested dir");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, result, "Hard_Link from file in nested dir");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "File exists at new path");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_bar_boffo),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_bar_boffo),
               "File still exists at old path");
     RAMFolder_Delete(folder, foo_bar_boffo);
 
@@ -442,19 +436,19 @@ test_Hard_Link(TestBatch *batch) {
     fh = RAMFolder_Open_FileHandle(folder, boffo, FH_CREATE | FH_WRITE_ONLY);
     DECREF(fh);
     result = RAMFolder_Hard_Link(folder, foo_boffo, boffo);
-    TEST_FALSE(batch, result, "Clobber of file fails");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, boffo),
+    TEST_FALSE(runner, result, "Clobber of file fails");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, boffo),
               "File still exists at new path");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "File still exists at old path");
     RAMFolder_Delete(folder, boffo);
 
     RAMFolder_MkDir(folder, baz);
     result = RAMFolder_Hard_Link(folder, foo_boffo, baz);
-    TEST_FALSE(batch, result, "Clobber of dir fails");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, baz),
+    TEST_FALSE(runner, result, "Clobber of dir fails");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, baz),
               "Dir still exists at new path");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "File still exists at old path");
     RAMFolder_Delete(folder, baz);
 
@@ -462,65 +456,65 @@ test_Hard_Link(TestBatch *batch) {
 
     RAMFolder_MkDir(folder, baz);
     result = RAMFolder_Hard_Link(folder, baz, banana);
-    TEST_FALSE(batch, result, "Hard_Link dir fails");
-    TEST_FALSE(batch, RAMFolder_Exists(folder, banana),
+    TEST_FALSE(runner, result, "Hard_Link dir fails");
+    TEST_FALSE(runner, RAMFolder_Exists(folder, banana),
                "Nothing at new path");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, baz),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, baz),
               "Folder still exists at old path");
     RAMFolder_Delete(folder, baz);
 
     // Test that linking to yourself fails.
 
     result = RAMFolder_Hard_Link(folder, foo_boffo, foo_boffo);
-    TEST_FALSE(batch, result, "Hard_Link file to itself fails");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_FALSE(runner, result, "Hard_Link file to itself fails");
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "File still exists");
 
     // Invalid filepaths.
 
     Err_set_error(NULL);
     result = RAMFolder_Rename(folder, foo_boffo, nope_nyet);
-    TEST_FALSE(batch, result, "Hard_Link into non-existent subdir fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Hard_Link into non-existent subdir fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Hard_Link into non-existent subdir sets Err_error");
-    TEST_TRUE(batch, RAMFolder_Exists(folder, foo_boffo),
+    TEST_TRUE(runner, RAMFolder_Exists(folder, foo_boffo),
               "Entry still exists at old path");
 
     Err_set_error(NULL);
     result = RAMFolder_Rename(folder, nope_nyet, boffo);
-    TEST_FALSE(batch, result, "Hard_Link non-existent source file fails");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Hard_Link non-existent source file fails");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Hard_Link non-existent source file sets Err_error");
 
     DECREF(folder);
 }
 
 static void
-test_Close(TestBatch *batch) {
+test_Close(TestBatchRunner *runner) {
     RAMFolder *folder = RAMFolder_new(NULL);
     RAMFolder_Close(folder);
-    PASS(batch, "Close() concludes without incident");
+    PASS(runner, "Close() concludes without incident");
     RAMFolder_Close(folder);
     RAMFolder_Close(folder);
-    PASS(batch, "Calling Close() multiple times is safe");
+    PASS(runner, "Calling Close() multiple times is safe");
     DECREF(folder);
 }
 
 void
-TestRAMFolder_run_tests(TestRAMFolder *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestRAMFolder_run(TestRAMFolder *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 98);
     S_init_strings();
-    test_Initialize_and_Check(batch);
-    test_Local_Exists(batch);
-    test_Local_Is_Directory(batch);
-    test_Local_Find_Folder(batch);
-    test_Local_MkDir(batch);
-    test_Local_Open_Dir(batch);
-    test_Local_Open_FileHandle(batch);
-    test_Local_Delete(batch);
-    test_Rename(batch);
-    test_Hard_Link(batch);
-    test_Close(batch);
+    test_Initialize_and_Check(runner);
+    test_Local_Exists(runner);
+    test_Local_Is_Directory(runner);
+    test_Local_Find_Folder(runner);
+    test_Local_MkDir(runner);
+    test_Local_Open_Dir(runner);
+    test_Local_Open_FileHandle(runner);
+    test_Local_Delete(runner);
+    test_Rename(runner);
+    test_Hard_Link(runner);
+    test_Close(runner);
     S_destroy_strings();
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Store/TestRAMFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFolder.cfh b/core/Lucy/Test/Store/TestRAMFolder.cfh
index 231e579..6fc392c 100644
--- a/core/Lucy/Test/Store/TestRAMFolder.cfh
+++ b/core/Lucy/Test/Store/TestRAMFolder.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Store::TestRAMFolder
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestRAMFolder*
-    new(TestFormatter *formatter);
-
-    inert TestRAMFolder*
-    init(TestRAMFolder *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestRAMFolder *self);
+    Run(TestRAMFolder *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/TestSchema.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestSchema.c b/core/Lucy/Test/TestSchema.c
index 847fa74..6dcb80e 100644
--- a/core/Lucy/Test/TestSchema.c
+++ b/core/Lucy/Test/TestSchema.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Plan/TestArchitecture.h"
 #include "Lucy/Test/TestSchema.h"
@@ -54,18 +54,12 @@ TestSchema_architecture(TestSchema *self) {
 }
 
 TestBatchSchema*
-TestBatchSchema_new(TestFormatter *formatter) {
-    TestBatchSchema *self = (TestBatchSchema*)VTable_Make_Obj(TESTBATCHSCHEMA);
-    return TestBatchSchema_init(self, formatter);
-}
-
-TestBatchSchema*
-TestBatchSchema_init(TestBatchSchema *self, TestFormatter *formatter) {
-    return (TestBatchSchema*)TestBatch_init((TestBatch*)self, 4, formatter);
+TestBatchSchema_new() {
+    return (TestBatchSchema*)VTable_Make_Obj(TESTBATCHSCHEMA);
 }
 
 static void
-test_Equals(TestBatch *batch) {
+test_Equals(TestBatchRunner *runner) {
     TestSchema *schema = TestSchema_new();
     TestSchema *arch_differs = TestSchema_new();
     TestSchema *spec_differs = TestSchema_new();
@@ -73,15 +67,15 @@ test_Equals(TestBatch *batch) {
     FullTextType *type = (FullTextType*)TestSchema_Fetch_Type(spec_differs,
                                                               content);
 
-    TEST_TRUE(batch, TestSchema_Equals(schema, (Obj*)schema), "Equals");
+    TEST_TRUE(runner, TestSchema_Equals(schema, (Obj*)schema), "Equals");
 
     FullTextType_Set_Boost(type, 2.0f);
-    TEST_FALSE(batch, TestSchema_Equals(schema, (Obj*)spec_differs),
+    TEST_FALSE(runner, TestSchema_Equals(schema, (Obj*)spec_differs),
                "Equals spoiled by differing FieldType");
 
     DECREF(arch_differs->arch);
     arch_differs->arch = Arch_new();
-    TEST_FALSE(batch, TestSchema_Equals(schema, (Obj*)arch_differs),
+    TEST_FALSE(runner, TestSchema_Equals(schema, (Obj*)arch_differs),
                "Equals spoiled by differing Architecture");
 
     DECREF(schema);
@@ -90,12 +84,12 @@ test_Equals(TestBatch *batch) {
 }
 
 static void
-test_Dump_and_Load(TestBatch *batch) {
+test_Dump_and_Load(TestBatchRunner *runner) {
     TestSchema *schema = TestSchema_new();
     Obj        *dump   = (Obj*)TestSchema_Dump(schema);
     TestSchema *loaded = (TestSchema*)Obj_Load(dump, dump);
 
-    TEST_FALSE(batch, TestSchema_Equals(schema, (Obj*)loaded),
+    TEST_FALSE(runner, TestSchema_Equals(schema, (Obj*)loaded),
                "Dump => Load round trip");
 
     DECREF(schema);
@@ -104,10 +98,10 @@ test_Dump_and_Load(TestBatch *batch) {
 }
 
 void
-TestBatchSchema_run_tests(TestBatchSchema *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Equals(batch);
-    test_Dump_and_Load(batch);
+TestBatchSchema_run(TestBatchSchema *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+    test_Equals(runner);
+    test_Dump_and_Load(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/TestSchema.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestSchema.cfh b/core/Lucy/Test/TestSchema.cfh
index 758c707..c422435 100644
--- a/core/Lucy/Test/TestSchema.cfh
+++ b/core/Lucy/Test/TestSchema.cfh
@@ -37,13 +37,10 @@ class Lucy::Test::TestBatchSchema
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestBatchSchema*
-    new(TestFormatter *formatter);
-
-    inert TestBatchSchema*
-    init(TestBatchSchema *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestBatchSchema *self);
+    Run(TestBatchSchema *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/TestUtils.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestUtils.c b/core/Lucy/Test/TestUtils.c
index e345338..6624389 100644
--- a/core/Lucy/Test/TestUtils.c
+++ b/core/Lucy/Test/TestUtils.c
@@ -21,7 +21,7 @@
 
 #include "Lucy/Test/TestUtils.h"
 #include "Lucy/Test.h"
-#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Lucy/Analysis/Analyzer.h"
 #include "Lucy/Analysis/Inversion.h"
@@ -127,8 +127,9 @@ TestUtils_make_range_query(const char *field, const char *lower_term,
 }
 
 void
-TestUtils_test_analyzer(TestBatch *batch, Analyzer *analyzer, CharBuf *source,
-                        VArray *expected, const char *message) {
+TestUtils_test_analyzer(TestBatchRunner *runner, Analyzer *analyzer,
+                        CharBuf *source, VArray *expected,
+                        const char *message) {
     Token *seed = Token_new((char*)CB_Get_Ptr8(source), CB_Get_Size(source),
                             0, 0, 1.0f, 1);
     Inversion *starter = Inversion_new(seed);
@@ -140,7 +141,7 @@ TestUtils_test_analyzer(TestBatch *batch, Analyzer *analyzer, CharBuf *source,
             = CB_new_from_utf8(Token_Get_Text(token), Token_Get_Len(token));
         VA_Push(got, (Obj*)token_text);
     }
-    TEST_TRUE(batch, VA_Equals(expected, (Obj*)got),
+    TEST_TRUE(runner, VA_Equals(expected, (Obj*)got),
               "Transform(): %s", message);
     DECREF(transformed);
 
@@ -151,13 +152,13 @@ TestUtils_test_analyzer(TestBatch *batch, Analyzer *analyzer, CharBuf *source,
             = CB_new_from_utf8(Token_Get_Text(token), Token_Get_Len(token));
         VA_Push(got, (Obj*)token_text);
     }
-    TEST_TRUE(batch, VA_Equals(expected, (Obj*)got),
+    TEST_TRUE(runner, VA_Equals(expected, (Obj*)got),
               "Transform_Text(): %s", message);
     DECREF(transformed);
 
     DECREF(got);
     got = Analyzer_Split(analyzer, source);
-    TEST_TRUE(batch, VA_Equals(expected, (Obj*)got), "Split(): %s", message);
+    TEST_TRUE(runner, VA_Equals(expected, (Obj*)got), "Split(): %s", message);
 
     DECREF(got);
     DECREF(starter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/TestUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestUtils.cfh b/core/Lucy/Test/TestUtils.cfh
index 189ad0a..9dc07ad 100644
--- a/core/Lucy/Test/TestUtils.cfh
+++ b/core/Lucy/Test/TestUtils.cfh
@@ -62,7 +62,7 @@ inert class Lucy::Test::TestUtils  {
     /** Verify an Analyzer's transform, transform_text, and split methods.
      */
     inert void
-    test_analyzer(TestBatch *batch, Analyzer *analyzer, CharBuf *source,
+    test_analyzer(TestBatchRunner *runner, Analyzer *analyzer, CharBuf *source,
                   VArray *expected, const char *message);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Util/TestIndexFileNames.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestIndexFileNames.c b/core/Lucy/Test/Util/TestIndexFileNames.c
index 5f7e41a..b3f89ed 100644
--- a/core/Lucy/Test/Util/TestIndexFileNames.c
+++ b/core/Lucy/Test/Util/TestIndexFileNames.c
@@ -17,78 +17,72 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Util/TestIndexFileNames.h"
 #include "Lucy/Util/IndexFileNames.h"
 
 TestIndexFileNames*
-TestIxFileNames_new(TestFormatter *formatter) {
-    TestIndexFileNames *self = (TestIndexFileNames*)VTable_Make_Obj(TESTINDEXFILENAMES);
-    return TestIxFileNames_init(self, formatter);
-}
-
-TestIndexFileNames*
-TestIxFileNames_init(TestIndexFileNames *self, TestFormatter *formatter) {
-    return (TestIndexFileNames*)TestBatch_init((TestBatch*)self, 10, formatter);
+TestIxFileNames_new() {
+    return (TestIndexFileNames*)VTable_Make_Obj(TESTINDEXFILENAMES);
 }
 
 static void
-test_local_part(TestBatch *batch) {
+test_local_part(TestBatchRunner *runner) {
     ZombieCharBuf *source = ZCB_BLANK();
     ZombieCharBuf *got    = ZCB_BLANK();
 
     got = IxFileNames_local_part((CharBuf*)source, got);
-    TEST_TRUE(batch, ZCB_Equals(got, (Obj*)source), "simple name");
+    TEST_TRUE(runner, ZCB_Equals(got, (Obj*)source), "simple name");
 
     ZCB_Assign_Str(source, "foo.txt", 7);
     got = IxFileNames_local_part((CharBuf*)source, got);
-    TEST_TRUE(batch, ZCB_Equals(got, (Obj*)source), "name with extension");
+    TEST_TRUE(runner, ZCB_Equals(got, (Obj*)source), "name with extension");
 
     ZCB_Assign_Str(source, "/foo", 4);
     got = IxFileNames_local_part((CharBuf*)source, got);
-    TEST_TRUE(batch, ZCB_Equals_Str(got, "foo", 3), "strip leading slash");
+    TEST_TRUE(runner, ZCB_Equals_Str(got, "foo", 3), "strip leading slash");
 
     ZCB_Assign_Str(source, "/foo/", 5);
     got = IxFileNames_local_part((CharBuf*)source, got);
-    TEST_TRUE(batch, ZCB_Equals_Str(got, "foo", 3), "strip trailing slash");
+    TEST_TRUE(runner, ZCB_Equals_Str(got, "foo", 3), "strip trailing slash");
 
     ZCB_Assign_Str(source, "foo/bar\\ ", 9);
     got = IxFileNames_local_part((CharBuf*)source, got);
-    TEST_TRUE(batch, ZCB_Equals_Str(got, "bar\\ ", 5),
+    TEST_TRUE(runner, ZCB_Equals_Str(got, "bar\\ ", 5),
               "Include garbage like backslashes and spaces");
 
     ZCB_Assign_Str(source, "foo/bar/baz.txt", 15);
     got = IxFileNames_local_part((CharBuf*)source, got);
-    TEST_TRUE(batch, ZCB_Equals_Str(got, "baz.txt", 7), "find last component");
+    TEST_TRUE(runner, ZCB_Equals_Str(got, "baz.txt", 7), "find last component");
 }
 
 static void
-test_extract_gen(TestBatch *batch) {
+test_extract_gen(TestBatchRunner *runner) {
     ZombieCharBuf *source = ZCB_WRAP_STR("", 0);
 
     ZCB_Assign_Str(source, "seg_9", 5);
-    TEST_TRUE(batch, IxFileNames_extract_gen((CharBuf*)source) == 9,
+    TEST_TRUE(runner, IxFileNames_extract_gen((CharBuf*)source) == 9,
               "extract_gen");
 
     ZCB_Assign_Str(source, "seg_9/", 6);
-    TEST_TRUE(batch, IxFileNames_extract_gen((CharBuf*)source) == 9,
+    TEST_TRUE(runner, IxFileNames_extract_gen((CharBuf*)source) == 9,
               "deal with trailing slash");
 
     ZCB_Assign_Str(source, "seg_9_8", 7);
-    TEST_TRUE(batch, IxFileNames_extract_gen((CharBuf*)source) == 9,
+    TEST_TRUE(runner, IxFileNames_extract_gen((CharBuf*)source) == 9,
               "Only go past first underscore");
 
     ZCB_Assign_Str(source, "snapshot_5.json", 15);
-    TEST_TRUE(batch, IxFileNames_extract_gen((CharBuf*)source) == 5,
+    TEST_TRUE(runner, IxFileNames_extract_gen((CharBuf*)source) == 5,
               "Deal with file suffix");
 }
 
 void
-TestIxFileNames_run_tests(TestIndexFileNames *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_local_part(batch);
-    test_extract_gen(batch);
+TestIxFileNames_run(TestIndexFileNames *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 10);
+    test_local_part(runner);
+    test_extract_gen(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Util/TestIndexFileNames.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestIndexFileNames.cfh b/core/Lucy/Test/Util/TestIndexFileNames.cfh
index 44323de..e098c72 100644
--- a/core/Lucy/Test/Util/TestIndexFileNames.cfh
+++ b/core/Lucy/Test/Util/TestIndexFileNames.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Util::TestIndexFileNames cnick TestIxFileNames
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestIndexFileNames*
-    new(TestFormatter *formatter);
-
-    inert TestIndexFileNames*
-    init(TestIndexFileNames *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestIndexFileNames *self);
+    Run(TestIndexFileNames *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Util/TestJson.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestJson.c b/core/Lucy/Test/Util/TestJson.c
index 7be389a..8962c8c 100644
--- a/core/Lucy/Test/Util/TestJson.c
+++ b/core/Lucy/Test/Util/TestJson.c
@@ -18,7 +18,7 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Util/TestJson.h"
 #include "Lucy/Util/Json.h"
@@ -26,18 +26,8 @@
 #include "Lucy/Store/RAMFolder.h"
 
 TestJson*
-TestJson_new(TestFormatter *formatter) {
-    TestJson *self = (TestJson*)VTable_Make_Obj(TESTJSON);
-    return TestJson_init(self, formatter);
-}
-
-TestJson*
-TestJson_init(TestJson *self, TestFormatter *formatter) {
-    int num_tests = 107;
-#ifndef LUCY_VALGRIND
-    num_tests += 28; // FIXME: syntax errors leak memory.
-#endif
-    return (TestJson*)TestBatch_init((TestBatch*)self, num_tests, formatter);
+TestJson_new() {
+    return (TestJson*)VTable_Make_Obj(TESTJSON);
 }
 
 // Create a test data structure including at least one each of Hash, VArray,
@@ -51,12 +41,12 @@ S_make_dump() {
 }
 
 static void
-test_tolerance(TestBatch *batch) {
+test_tolerance(TestBatchRunner *runner) {
     CharBuf *foo = CB_newf("foo");
     CharBuf *not_json = Json_to_json((Obj*)foo);
-    TEST_TRUE(batch, not_json == NULL,
+    TEST_TRUE(runner, not_json == NULL,
               "to_json returns NULL when fed invalid data type");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "to_json sets Err_error when fed invalid data type");
     DECREF(foo);
 }
@@ -123,7 +113,7 @@ static const char* quote_escapes_json[] = {
 };
 
 static void
-test_escapes(TestBatch *batch) {
+test_escapes(TestBatchRunner *runner) {
     CharBuf *string      = CB_new(10);
     CharBuf *json_wanted = CB_new(10);
 
@@ -136,10 +126,10 @@ test_escapes(TestBatch *batch) {
 
         CB_setf(json_wanted, "\"%s\"", escaped);
         CB_Trim(json);
-        TEST_TRUE(batch, json != NULL && CB_Equals(json_wanted, (Obj*)json),
+        TEST_TRUE(runner, json != NULL && CB_Equals(json_wanted, (Obj*)json),
                   "encode control escape: %s", escaped);
 
-        TEST_TRUE(batch, decoded != NULL && CB_Equals(string, (Obj*)decoded),
+        TEST_TRUE(runner, decoded != NULL && CB_Equals(string, (Obj*)decoded),
                   "decode control escape: %s", escaped);
 
         DECREF(json);
@@ -155,10 +145,10 @@ test_escapes(TestBatch *batch) {
 
         CB_setf(json_wanted, "\"%s\"", escaped);
         CB_Trim(json);
-        TEST_TRUE(batch, json != NULL && CB_Equals(json_wanted, (Obj*)json),
+        TEST_TRUE(runner, json != NULL && CB_Equals(json_wanted, (Obj*)json),
                   "encode quote/backslash escapes: %s", source);
 
-        TEST_TRUE(batch, decoded != NULL && CB_Equals(string, (Obj*)decoded),
+        TEST_TRUE(runner, decoded != NULL && CB_Equals(string, (Obj*)decoded),
                   "decode quote/backslash escapes: %s", source);
 
         DECREF(json);
@@ -170,11 +160,11 @@ test_escapes(TestBatch *batch) {
 }
 
 static void
-test_numbers(TestBatch *batch) {
+test_numbers(TestBatchRunner *runner) {
     Integer64 *i64  = Int64_new(33);
     CharBuf   *json = Json_to_json((Obj*)i64);
     CB_Trim(json);
-    TEST_TRUE(batch, json && CB_Equals_Str(json, "33", 2), "Integer");
+    TEST_TRUE(runner, json && CB_Equals_Str(json, "33", 2), "Integer");
     DECREF(json);
 
     Float64 *f64 = Float64_new(33.33);
@@ -183,11 +173,11 @@ test_numbers(TestBatch *batch) {
         double value = CB_To_F64(json);
         double diff = 33.33 - value;
         if (diff < 0.0) { diff = 0.0 - diff; }
-        TEST_TRUE(batch, diff < 0.0001, "Float");
+        TEST_TRUE(runner, diff < 0.0001, "Float");
         DECREF(json);
     }
     else {
-        FAIL(batch, "Float conversion to  json  failed.");
+        FAIL(runner, "Float conversion to  json  failed.");
     }
 
     DECREF(i64);
@@ -195,11 +185,11 @@ test_numbers(TestBatch *batch) {
 }
 
 static void
-test_to_and_from(TestBatch *batch) {
+test_to_and_from(TestBatchRunner *runner) {
     Obj *dump = S_make_dump();
     CharBuf *json = Json_to_json(dump);
     Obj *got = Json_from_json(json);
-    TEST_TRUE(batch, got != NULL && Obj_Equals(dump, got),
+    TEST_TRUE(runner, got != NULL && Obj_Equals(dump, got),
               "Round trip through to_json and from_json");
     DECREF(dump);
     DECREF(json);
@@ -207,33 +197,33 @@ test_to_and_from(TestBatch *batch) {
 }
 
 static void
-test_spew_and_slurp(TestBatch *batch) {
+test_spew_and_slurp(TestBatchRunner *runner) {
     Obj *dump = S_make_dump();
     Folder *folder = (Folder*)RAMFolder_new(NULL);
 
     CharBuf *foo = (CharBuf*)ZCB_WRAP_STR("foo", 3);
     bool result = Json_spew_json(dump, folder, foo);
-    TEST_TRUE(batch, result, "spew_json returns true on success");
-    TEST_TRUE(batch, Folder_Exists(folder, foo),
+    TEST_TRUE(runner, result, "spew_json returns true on success");
+    TEST_TRUE(runner, Folder_Exists(folder, foo),
               "spew_json wrote file");
 
     Obj *got = Json_slurp_json(folder, foo);
-    TEST_TRUE(batch, got && Obj_Equals(dump, got),
+    TEST_TRUE(runner, got && Obj_Equals(dump, got),
               "Round trip through spew_json and slurp_json");
     DECREF(got);
 
     Err_set_error(NULL);
     result = Json_spew_json(dump, folder, foo);
-    TEST_FALSE(batch, result, "Can't spew_json when file exists");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_FALSE(runner, result, "Can't spew_json when file exists");
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Failed spew_json sets Err_error");
 
     Err_set_error(NULL);
     CharBuf *bar = (CharBuf*)ZCB_WRAP_STR("bar", 3);
     got = Json_slurp_json(folder, bar);
-    TEST_TRUE(batch, got == NULL,
+    TEST_TRUE(runner, got == NULL,
               "slurp_json returns NULL when file doesn't exist");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Failed slurp_json sets Err_error");
 
     CharBuf *boffo = (CharBuf*)ZCB_WRAP_STR("boffo", 5);
@@ -245,9 +235,9 @@ test_spew_and_slurp(TestBatch *batch) {
 
     Err_set_error(NULL);
     got = Json_slurp_json(folder, boffo);
-    TEST_TRUE(batch, got == NULL,
+    TEST_TRUE(runner, got == NULL,
               "slurp_json returns NULL when file doesn't contain valid JSON");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "Failed slurp_json sets Err_error");
     DECREF(got);
 
@@ -256,44 +246,44 @@ test_spew_and_slurp(TestBatch *batch) {
 }
 
 static void
-S_verify_bad_syntax(TestBatch *batch, const char *bad, const char *mess) {
+S_verify_bad_syntax(TestBatchRunner *runner, const char *bad, const char *mess) {
     ZombieCharBuf *has_errors = ZCB_WRAP_STR(bad, strlen(bad));
     Err_set_error(NULL);
     Obj *not_json = Json_from_json((CharBuf*)has_errors);
-    TEST_TRUE(batch, not_json == NULL, "from_json returns NULL: %s", mess);
-    TEST_TRUE(batch, Err_get_error() != NULL, "from_json sets Err_error: %s",
+    TEST_TRUE(runner, not_json == NULL, "from_json returns NULL: %s", mess);
+    TEST_TRUE(runner, Err_get_error() != NULL, "from_json sets Err_error: %s",
               mess);
 }
 
 static void
-test_syntax_errors(TestBatch *batch) {
-    S_verify_bad_syntax(batch, "[", "unclosed left bracket");
-    S_verify_bad_syntax(batch, "]", "unopened right bracket");
-    S_verify_bad_syntax(batch, "{", "unclosed left curly");
-    S_verify_bad_syntax(batch, "}", "unopened right curly");
-    S_verify_bad_syntax(batch, "{}[]", "two top-level objects");
-    S_verify_bad_syntax(batch, "[1 \"foo\"]", "missing comma in array");
-    S_verify_bad_syntax(batch, "[1, \"foo\",]", "extra comma in array");
-    S_verify_bad_syntax(batch, "{\"1\":1 \"2\":2}", "missing comma in hash");
-    S_verify_bad_syntax(batch, "{\"1\":1,\"2\":2,}", "extra comma in hash");
-    S_verify_bad_syntax(batch, "\"1", "unterminated string");
+test_syntax_errors(TestBatchRunner *runner) {
+    S_verify_bad_syntax(runner, "[", "unclosed left bracket");
+    S_verify_bad_syntax(runner, "]", "unopened right bracket");
+    S_verify_bad_syntax(runner, "{", "unclosed left curly");
+    S_verify_bad_syntax(runner, "}", "unopened right curly");
+    S_verify_bad_syntax(runner, "{}[]", "two top-level objects");
+    S_verify_bad_syntax(runner, "[1 \"foo\"]", "missing comma in array");
+    S_verify_bad_syntax(runner, "[1, \"foo\",]", "extra comma in array");
+    S_verify_bad_syntax(runner, "{\"1\":1 \"2\":2}", "missing comma in hash");
+    S_verify_bad_syntax(runner, "{\"1\":1,\"2\":2,}", "extra comma in hash");
+    S_verify_bad_syntax(runner, "\"1", "unterminated string");
     // Tolerated by strtod().
-    // S_verify_bad_syntax(batch, "1. ", "float missing fraction");
-    // S_verify_bad_syntax(batch, "-.3 ", "Number missing integral part");
-    S_verify_bad_syntax(batch, "-. ", "Number missing any digits");
-    S_verify_bad_syntax(batch, "+1.0 ", "float with prepended plus");
-    S_verify_bad_syntax(batch, "\"\\g\"", "invalid char escape");
-    S_verify_bad_syntax(batch, "\"\\uAAAZ\"", "invalid \\u escape");
+    // S_verify_bad_syntax(runner, "1. ", "float missing fraction");
+    // S_verify_bad_syntax(runner, "-.3 ", "Number missing integral part");
+    S_verify_bad_syntax(runner, "-. ", "Number missing any digits");
+    S_verify_bad_syntax(runner, "+1.0 ", "float with prepended plus");
+    S_verify_bad_syntax(runner, "\"\\g\"", "invalid char escape");
+    S_verify_bad_syntax(runner, "\"\\uAAAZ\"", "invalid \\u escape");
 }
 
 static void
-S_round_trip_integer(TestBatch *batch, int64_t value) {
+S_round_trip_integer(TestBatchRunner *runner, int64_t value) {
     Integer64 *num = Int64_new(value);
     VArray *array = VA_new(1);
     VA_Store(array, 0, (Obj*)num);
     CharBuf *json = Json_to_json((Obj*)array);
     Obj *dump = Json_from_json(json);
-    TEST_TRUE(batch, VA_Equals(array, dump), "Round trip integer %ld",
+    TEST_TRUE(runner, VA_Equals(array, dump), "Round trip integer %ld",
               (long)value);
     DECREF(dump);
     DECREF(json);
@@ -301,15 +291,15 @@ S_round_trip_integer(TestBatch *batch, int64_t value) {
 }
 
 static void
-test_integers(TestBatch *batch) {
-    S_round_trip_integer(batch, 0);
-    S_round_trip_integer(batch, -1);
-    S_round_trip_integer(batch, -1000000);
-    S_round_trip_integer(batch, 1000000);
+test_integers(TestBatchRunner *runner) {
+    S_round_trip_integer(runner, 0);
+    S_round_trip_integer(runner, -1);
+    S_round_trip_integer(runner, -1000000);
+    S_round_trip_integer(runner, 1000000);
 }
 
 static void
-S_round_trip_float(TestBatch *batch, double value, double max_diff) {
+S_round_trip_float(TestBatchRunner *runner, double value, double max_diff) {
     Float64 *num = Float64_new(value);
     VArray *array = VA_new(1);
     VA_Store(array, 0, (Obj*)num);
@@ -318,69 +308,73 @@ S_round_trip_float(TestBatch *batch, double value, double max_diff) {
     Float64 *got = (Float64*)CERTIFY(VA_Fetch((VArray*)dump, 0), FLOAT64);
     double diff = Float64_Get_Value(num) - Float64_Get_Value(got);
     if (diff < 0) { diff = 0 - diff; }
-    TEST_TRUE(batch, diff <= max_diff, "Round trip float %f", value);
+    TEST_TRUE(runner, diff <= max_diff, "Round trip float %f", value);
     DECREF(dump);
     DECREF(json);
     DECREF(array);
 }
 
 static void
-test_floats(TestBatch *batch) {
-    S_round_trip_float(batch, 0.0, 0.0);
-    S_round_trip_float(batch, 0.1, 0.00001);
-    S_round_trip_float(batch, -0.1, 0.00001);
-    S_round_trip_float(batch, 1000000.5, 1.0);
-    S_round_trip_float(batch, -1000000.5, 1.0);
+test_floats(TestBatchRunner *runner) {
+    S_round_trip_float(runner, 0.0, 0.0);
+    S_round_trip_float(runner, 0.1, 0.00001);
+    S_round_trip_float(runner, -0.1, 0.00001);
+    S_round_trip_float(runner, 1000000.5, 1.0);
+    S_round_trip_float(runner, -1000000.5, 1.0);
 }
 
 static void
-test_max_depth(TestBatch *batch) {
+test_max_depth(TestBatchRunner *runner) {
     Hash *circular = Hash_new(0);
     Hash_Store_Str(circular, "circular", 8, INCREF(circular));
     Err_set_error(NULL);
     CharBuf *not_json = Json_to_json((Obj*)circular);
-    TEST_TRUE(batch, not_json == NULL,
+    TEST_TRUE(runner, not_json == NULL,
               "to_json returns NULL when fed recursing data");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "to_json sets Err_error when fed recursing data");
     DECREF(Hash_Delete_Str(circular, "circular", 8));
     DECREF(circular);
 }
 
 static void
-test_illegal_keys(TestBatch *batch) {
+test_illegal_keys(TestBatchRunner *runner) {
     Hash *hash = Hash_new(0);
     Float64 *key = Float64_new(1.1);
     Hash_Store(hash, (Obj*)key, (Obj*)CB_newf("blah"));
     Err_set_error(NULL);
     CharBuf *not_json = Json_to_json((Obj*)hash);
-    TEST_TRUE(batch, not_json == NULL,
+    TEST_TRUE(runner, not_json == NULL,
               "to_json returns NULL when fed an illegal key");
-    TEST_TRUE(batch, Err_get_error() != NULL,
+    TEST_TRUE(runner, Err_get_error() != NULL,
               "to_json sets Err_error when fed an illegal key");
     DECREF(key);
     DECREF(hash);
 }
 
 void
-TestJson_run_tests(TestJson *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestJson_run(TestJson *self, TestBatchRunner *runner) {
+    uint32_t num_tests = 107;
+#ifndef LUCY_VALGRIND
+    num_tests += 28; // FIXME: syntax errors leak memory.
+#endif
+    TestBatchRunner_Plan(runner, (TestBatch*)self, num_tests);
 
     // Test tolerance, then liberalize for testing.
-    test_tolerance(batch);
+    test_tolerance(runner);
     Json_set_tolerant(true);
 
-    test_to_and_from(batch);
-    test_escapes(batch);
-    test_numbers(batch);
-    test_spew_and_slurp(batch);
-    test_integers(batch);
-    test_floats(batch);
-    test_max_depth(batch);
-    test_illegal_keys(batch);
+    test_to_and_from(runner);
+    test_escapes(runner);
+    test_numbers(runner);
+    test_spew_and_slurp(runner);
+    test_integers(runner);
+    test_floats(runner);
+    test_max_depth(runner);
+    test_illegal_keys(runner);
 
 #ifndef LUCY_VALGRIND
-    test_syntax_errors(batch);
+    test_syntax_errors(runner);
 #endif
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Util/TestJson.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestJson.cfh b/core/Lucy/Test/Util/TestJson.cfh
index f077492..ddba309 100644
--- a/core/Lucy/Test/Util/TestJson.cfh
+++ b/core/Lucy/Test/Util/TestJson.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Util::TestJson
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestJson*
-    new(TestFormatter *formatter);
-
-    inert TestJson*
-    init(TestJson *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestJson *self);
+    Run(TestJson *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Util/TestMemoryPool.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestMemoryPool.c b/core/Lucy/Test/Util/TestMemoryPool.c
index 69b5620..d671467 100644
--- a/core/Lucy/Test/Util/TestMemoryPool.c
+++ b/core/Lucy/Test/Util/TestMemoryPool.c
@@ -19,25 +19,20 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Util/TestMemoryPool.h"
 #include "Lucy/Util/MemoryPool.h"
 
 TestMemoryPool*
-TestMemPool_new(TestFormatter *formatter) {
-    TestMemoryPool *self = (TestMemoryPool*)VTable_Make_Obj(TESTMEMORYPOOL);
-    return TestMemPool_init(self, formatter);
-}
-
-TestMemoryPool*
-TestMemPool_init(TestMemoryPool *self, TestFormatter *formatter) {
-    return (TestMemoryPool*)TestBatch_init((TestBatch*)self, 4, formatter);
+TestMemPool_new() {
+    return (TestMemoryPool*)VTable_Make_Obj(TESTMEMORYPOOL);
 }
 
 void
-TestMemPool_run_tests(TestMemoryPool *self) {
-    TestBatch  *batch    = (TestBatch*)self;
+TestMemPool_run(TestMemoryPool *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+
     MemoryPool *mem_pool = MemPool_new(0);
     MemoryPool *other    = MemPool_new(0);
     char *ptr_a, *ptr_b;
@@ -47,17 +42,17 @@ TestMemPool_run_tests(TestMemoryPool *self) {
     MemPool_Release_All(mem_pool);
 
     ptr_b = (char*)MemPool_Grab(mem_pool, 10);
-    TEST_STR_EQ(batch, ptr_b, "foo", "Recycle RAM on Release_All");
+    TEST_STR_EQ(runner, ptr_b, "foo", "Recycle RAM on Release_All");
 
     ptr_a = mem_pool->buf;
     MemPool_Resize(mem_pool, ptr_b, 6);
-    TEST_TRUE(batch, mem_pool->buf < ptr_a, "Resize");
+    TEST_TRUE(runner, mem_pool->buf < ptr_a, "Resize");
 
     ptr_a = (char*)MemPool_Grab(other, 20);
     MemPool_Release_All(other);
     MemPool_Eat(other, mem_pool);
-    TEST_TRUE(batch, other->buf == mem_pool->buf, "Eat");
-    TEST_TRUE(batch, other->buf != NULL, "Eat");
+    TEST_TRUE(runner, other->buf == mem_pool->buf, "Eat");
+    TEST_TRUE(runner, other->buf != NULL, "Eat");
 
     DECREF(mem_pool);
     DECREF(other);

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Util/TestMemoryPool.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestMemoryPool.cfh b/core/Lucy/Test/Util/TestMemoryPool.cfh
index 378567a..f7ba344 100644
--- a/core/Lucy/Test/Util/TestMemoryPool.cfh
+++ b/core/Lucy/Test/Util/TestMemoryPool.cfh
@@ -20,13 +20,10 @@ class Lucy::Test::Util::TestMemoryPool cnick TestMemPool
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestMemoryPool*
-    new(TestFormatter *formatter);
-
-    inert TestMemoryPool*
-    init(TestMemoryPool *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestMemoryPool *self);
+    Run(TestMemoryPool *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Util/TestPriorityQueue.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestPriorityQueue.c b/core/Lucy/Test/Util/TestPriorityQueue.c
index 56dc58c..67bd20c 100644
--- a/core/Lucy/Test/Util/TestPriorityQueue.c
+++ b/core/Lucy/Test/Util/TestPriorityQueue.c
@@ -18,20 +18,14 @@
 #define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Lucy/Test.h"
 #include "Lucy/Test/Util/TestPriorityQueue.h"
 #include "Lucy/Util/PriorityQueue.h"
 
 TestPriorityQueue*
-TestPriQ_new(TestFormatter *formatter) {
-    TestPriorityQueue *self = (TestPriorityQueue*)VTable_Make_Obj(TESTPRIORITYQUEUE);
-    return TestPriQ_init(self, formatter);
-}
-
-TestPriorityQueue*
-TestPriQ_init(TestPriorityQueue *self, TestFormatter *formatter) {
-    return (TestPriorityQueue*)TestBatch_init((TestBatch*)self, 17, formatter);
+TestPriQ_new() {
+    return (TestPriorityQueue*)VTable_Make_Obj(TESTPRIORITYQUEUE);
 }
 
 NumPriorityQueue*
@@ -65,7 +59,7 @@ S_pop_num(NumPriorityQueue *pq) {
 }
 
 static void
-test_Peek_and_Pop_All(TestBatch *batch) {
+test_Peek_and_Pop_All(TestBatchRunner *runner) {
     NumPriorityQueue *pq = NumPriQ_new(5);
     Float64 *val;
 
@@ -75,27 +69,27 @@ test_Peek_and_Pop_All(TestBatch *batch) {
     S_insert_num(pq, 20);
     S_insert_num(pq, 10);
     val = (Float64*)CERTIFY(NumPriQ_Peek(pq), FLOAT64);
-    TEST_INT_EQ(batch, (long)Float64_Get_Value(val), 1,
+    TEST_INT_EQ(runner, (long)Float64_Get_Value(val), 1,
                 "peek at the least item in the queue");
 
     VArray  *got = NumPriQ_Pop_All(pq);
     val = (Float64*)CERTIFY(VA_Fetch(got, 0), FLOAT64);
-    TEST_INT_EQ(batch, (long)Float64_Get_Value(val), 20, "pop_all");
+    TEST_INT_EQ(runner, (long)Float64_Get_Value(val), 20, "pop_all");
     val = (Float64*)CERTIFY(VA_Fetch(got, 1), FLOAT64);
-    TEST_INT_EQ(batch, (long)Float64_Get_Value(val), 10, "pop_all");
+    TEST_INT_EQ(runner, (long)Float64_Get_Value(val), 10, "pop_all");
     val = (Float64*)CERTIFY(VA_Fetch(got, 2), FLOAT64);
-    TEST_INT_EQ(batch, (long)Float64_Get_Value(val),  3, "pop_all");
+    TEST_INT_EQ(runner, (long)Float64_Get_Value(val),  3, "pop_all");
     val = (Float64*)CERTIFY(VA_Fetch(got, 3), FLOAT64);
-    TEST_INT_EQ(batch, (long)Float64_Get_Value(val),  2, "pop_all");
+    TEST_INT_EQ(runner, (long)Float64_Get_Value(val),  2, "pop_all");
     val = (Float64*)CERTIFY(VA_Fetch(got, 4), FLOAT64);
-    TEST_INT_EQ(batch, (long)Float64_Get_Value(val),  1, "pop_all");
+    TEST_INT_EQ(runner, (long)Float64_Get_Value(val),  1, "pop_all");
 
     DECREF(got);
     DECREF(pq);
 }
 
 static void
-test_Insert_and_Pop(TestBatch *batch) {
+test_Insert_and_Pop(TestBatchRunner *runner) {
     NumPriorityQueue *pq = NumPriQ_new(5);
 
     S_insert_num(pq, 3);
@@ -104,20 +98,20 @@ test_Insert_and_Pop(TestBatch *batch) {
     S_insert_num(pq, 20);
     S_insert_num(pq, 10);
 
-    TEST_INT_EQ(batch, S_pop_num(pq), 1, "Pop");
-    TEST_INT_EQ(batch, S_pop_num(pq), 2, "Pop");
-    TEST_INT_EQ(batch, S_pop_num(pq), 3, "Pop");
-    TEST_INT_EQ(batch, S_pop_num(pq), 10, "Pop");
+    TEST_INT_EQ(runner, S_pop_num(pq), 1, "Pop");
+    TEST_INT_EQ(runner, S_pop_num(pq), 2, "Pop");
+    TEST_INT_EQ(runner, S_pop_num(pq), 3, "Pop");
+    TEST_INT_EQ(runner, S_pop_num(pq), 10, "Pop");
 
     S_insert_num(pq, 7);
-    TEST_INT_EQ(batch, S_pop_num(pq), 7,
+    TEST_INT_EQ(runner, S_pop_num(pq), 7,
                 "Insert after Pop still sorts correctly");
 
     DECREF(pq);
 }
 
 static void
-test_discard(TestBatch *batch) {
+test_discard(TestBatchRunner *runner) {
     int32_t i;
     NumPriorityQueue *pq = NumPriQ_new(5);
 
@@ -126,17 +120,17 @@ test_discard(TestBatch *batch) {
     for (i = 1590; i <= 1600; i++) { S_insert_num(pq, i); }
     S_insert_num(pq, 5);
 
-    TEST_INT_EQ(batch, S_pop_num(pq), 1596, "discard waste");
-    TEST_INT_EQ(batch, S_pop_num(pq), 1597, "discard waste");
-    TEST_INT_EQ(batch, S_pop_num(pq), 1598, "discard waste");
-    TEST_INT_EQ(batch, S_pop_num(pq), 1599, "discard waste");
-    TEST_INT_EQ(batch, S_pop_num(pq), 1600, "discard waste");
+    TEST_INT_EQ(runner, S_pop_num(pq), 1596, "discard waste");
+    TEST_INT_EQ(runner, S_pop_num(pq), 1597, "discard waste");
+    TEST_INT_EQ(runner, S_pop_num(pq), 1598, "discard waste");
+    TEST_INT_EQ(runner, S_pop_num(pq), 1599, "discard waste");
+    TEST_INT_EQ(runner, S_pop_num(pq), 1600, "discard waste");
 
     DECREF(pq);
 }
 
 static void
-test_random_insertion(TestBatch *batch) {
+test_random_insertion(TestBatchRunner *runner) {
     int i;
     int shuffled[64];
     NumPriorityQueue *pq = NumPriQ_new(64);
@@ -152,18 +146,18 @@ test_random_insertion(TestBatch *batch) {
     for (i = 0; i < 64; i++) {
         if (S_pop_num(pq) != i) { break; }
     }
-    TEST_INT_EQ(batch, i, 64, "random insertion");
+    TEST_INT_EQ(runner, i, 64, "random insertion");
 
     DECREF(pq);
 }
 
 void
-TestPriQ_run_tests(TestPriorityQueue *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Peek_and_Pop_All(batch);
-    test_Insert_and_Pop(batch);
-    test_discard(batch);
-    test_random_insertion(batch);
+TestPriQ_run(TestPriorityQueue *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 17);
+    test_Peek_and_Pop_All(runner);
+    test_Insert_and_Pop(runner);
+    test_discard(runner);
+    test_random_insertion(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Lucy/Test/Util/TestPriorityQueue.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestPriorityQueue.cfh b/core/Lucy/Test/Util/TestPriorityQueue.cfh
index 02f591d..296c2f7 100644
--- a/core/Lucy/Test/Util/TestPriorityQueue.cfh
+++ b/core/Lucy/Test/Util/TestPriorityQueue.cfh
@@ -30,13 +30,10 @@ class Lucy::Test::Util::TestPriorityQueue cnick TestPriQ
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestPriorityQueue*
-    new(TestFormatter *formatter);
-
-    inert TestPriorityQueue*
-    init(TestPriorityQueue *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestPriorityQueue *self);
+    Run(TestPriorityQueue *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/perl/buildlib/Lucy/Build/Binding/Misc.pm
----------------------------------------------------------------------
diff --git a/perl/buildlib/Lucy/Build/Binding/Misc.pm b/perl/buildlib/Lucy/Build/Binding/Misc.pm
index e55382d..f27e83d 100644
--- a/perl/buildlib/Lucy/Build/Binding/Misc.pm
+++ b/perl/buildlib/Lucy/Build/Binding/Misc.pm
@@ -89,9 +89,11 @@ CODE:
     cfish_CharBuf *class_name = cfish_CB_newf("%s", package);
     cfish_TestFormatter *formatter
         = (cfish_TestFormatter*)cfish_TestFormatterTAP_new();
-    bool result = testcfish_Test_run_batch(class_name, formatter);
+    cfish_TestSuite *suite = testcfish_Test_create_test_suite();
+    bool result = Cfish_TestSuite_Run_Batch(suite, class_name, formatter);
     CFISH_DECREF(class_name);
     CFISH_DECREF(formatter);
+    CFISH_DECREF(suite);
 
     RETVAL = result;
 OUTPUT: RETVAL
@@ -117,9 +119,11 @@ CODE:
     cfish_CharBuf *class_name = cfish_CB_newf("%s", package);
     cfish_TestFormatter *formatter
         = (cfish_TestFormatter*)cfish_TestFormatterTAP_new();
-    bool result = testlucy_Test_run_batch(class_name, formatter);
+    cfish_TestSuite *suite = testlucy_Test_create_test_suite();
+    bool result = Cfish_TestSuite_Run_Batch(suite, class_name, formatter);
     CFISH_DECREF(class_name);
     CFISH_DECREF(formatter);
+    CFISH_DECREF(suite);
 
     RETVAL = result;
 OUTPUT: RETVAL


[lucy-commits] [25/26] Rework Clownfish test harness

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestVArray.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestVArray.c b/core/Clownfish/Test/TestVArray.c
index 110c01b..f342763 100644
--- a/core/Clownfish/Test/TestVArray.c
+++ b/core/Clownfish/Test/TestVArray.c
@@ -25,20 +25,14 @@
 #include "Clownfish/Err.h"
 #include "Clownfish/Num.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VArray.h"
 #include "Clownfish/VTable.h"
 
 TestVArray*
-TestVArray_new(TestFormatter *formatter) {
-    TestVArray *self = (TestVArray*)VTable_Make_Obj(TESTVARRAY);
-    return TestVArray_init(self, formatter);
-}
-
-TestVArray*
-TestVArray_init(TestVArray *self, TestFormatter *formatter) {
-    return (TestVArray*)TestBatch_init((TestBatch*)self, 45, formatter);
+TestVArray_new() {
+    return (TestVArray*)VTable_Make_Obj(TESTVARRAY);
 }
 
 static CharBuf*
@@ -47,38 +41,38 @@ S_new_cb(const char *text) {
 }
 
 static void
-test_Equals(TestBatch *batch) {
+test_Equals(TestBatchRunner *runner) {
     VArray *array = VA_new(0);
     VArray *other = VA_new(0);
     ZombieCharBuf *stuff = ZCB_WRAP_STR("stuff", 5);
 
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)other),
+    TEST_TRUE(runner, VA_Equals(array, (Obj*)other),
               "Empty arrays are equal");
 
     VA_Push(array, (Obj*)CFISH_TRUE);
-    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
+    TEST_FALSE(runner, VA_Equals(array, (Obj*)other),
                "Add one elem and Equals returns false");
 
     VA_Push(other, (Obj*)CFISH_TRUE);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)other),
+    TEST_TRUE(runner, VA_Equals(array, (Obj*)other),
               "Add a matching elem and Equals returns true");
 
     VA_Store(array, 2, (Obj*)CFISH_TRUE);
-    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
+    TEST_FALSE(runner, VA_Equals(array, (Obj*)other),
                "Add elem after a NULL and Equals returns false");
 
     VA_Store(other, 2, (Obj*)CFISH_TRUE);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)other),
+    TEST_TRUE(runner, VA_Equals(array, (Obj*)other),
               "Empty elems don't spoil Equals");
 
     VA_Store(other, 2, INCREF(stuff));
-    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
+    TEST_FALSE(runner, VA_Equals(array, (Obj*)other),
                "Non-matching value spoils Equals");
 
     VA_Excise(array, 1, 2); // removes empty elems
     VA_Delete(other, 1);    // leaves NULL in place of deleted elem
     VA_Delete(other, 2);
-    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
+    TEST_FALSE(runner, VA_Equals(array, (Obj*)other),
                "Empty trailing elements spoil Equals");
 
     DECREF(array);
@@ -86,63 +80,63 @@ test_Equals(TestBatch *batch) {
 }
 
 static void
-test_Store_Fetch(TestBatch *batch) {
+test_Store_Fetch(TestBatchRunner *runner) {
     VArray *array = VA_new(0);
     CharBuf *elem;
 
-    TEST_TRUE(batch, VA_Fetch(array, 2) == NULL, "Fetch beyond end");
+    TEST_TRUE(runner, VA_Fetch(array, 2) == NULL, "Fetch beyond end");
 
     VA_Store(array, 2, (Obj*)CB_newf("foo"));
     elem = (CharBuf*)CERTIFY(VA_Fetch(array, 2), CHARBUF);
-    TEST_INT_EQ(batch, 3, VA_Get_Size(array), "Store updates size");
-    TEST_TRUE(batch, CB_Equals_Str(elem, "foo", 3), "Store");
+    TEST_INT_EQ(runner, 3, VA_Get_Size(array), "Store updates size");
+    TEST_TRUE(runner, CB_Equals_Str(elem, "foo", 3), "Store");
 
     INCREF(elem);
-    TEST_INT_EQ(batch, 2, CB_Get_RefCount(elem),
+    TEST_INT_EQ(runner, 2, CB_Get_RefCount(elem),
                 "start with refcount of 2");
     VA_Store(array, 2, (Obj*)CB_newf("bar"));
-    TEST_INT_EQ(batch, 1, CB_Get_RefCount(elem),
+    TEST_INT_EQ(runner, 1, CB_Get_RefCount(elem),
                 "Displacing elem via Store updates refcount");
     DECREF(elem);
     elem = (CharBuf*)CERTIFY(VA_Fetch(array, 2), CHARBUF);
-    TEST_TRUE(batch, CB_Equals_Str(elem, "bar", 3), "Store displacement");
+    TEST_TRUE(runner, CB_Equals_Str(elem, "bar", 3), "Store displacement");
 
     DECREF(array);
 }
 
 static void
-test_Push_Pop_Shift_Unshift(TestBatch *batch) {
+test_Push_Pop_Shift_Unshift(TestBatchRunner *runner) {
     VArray *array = VA_new(0);
     CharBuf *elem;
 
-    TEST_INT_EQ(batch, VA_Get_Size(array), 0, "size starts at 0");
+    TEST_INT_EQ(runner, VA_Get_Size(array), 0, "size starts at 0");
     VA_Push(array, (Obj*)CB_newf("a"));
     VA_Push(array, (Obj*)CB_newf("b"));
     VA_Push(array, (Obj*)CB_newf("c"));
 
-    TEST_INT_EQ(batch, VA_Get_Size(array), 3, "size after Push");
-    TEST_TRUE(batch, NULL != CERTIFY(VA_Fetch(array, 2), CHARBUF), "Push");
+    TEST_INT_EQ(runner, VA_Get_Size(array), 3, "size after Push");
+    TEST_TRUE(runner, NULL != CERTIFY(VA_Fetch(array, 2), CHARBUF), "Push");
 
     elem = (CharBuf*)CERTIFY(VA_Shift(array), CHARBUF);
-    TEST_TRUE(batch, CB_Equals_Str(elem, "a", 1), "Shift");
-    TEST_INT_EQ(batch, VA_Get_Size(array), 2, "size after Shift");
+    TEST_TRUE(runner, CB_Equals_Str(elem, "a", 1), "Shift");
+    TEST_INT_EQ(runner, VA_Get_Size(array), 2, "size after Shift");
     DECREF(elem);
 
     elem = (CharBuf*)CERTIFY(VA_Pop(array), CHARBUF);
-    TEST_TRUE(batch, CB_Equals_Str(elem, "c", 1), "Pop");
-    TEST_INT_EQ(batch, VA_Get_Size(array), 1, "size after Pop");
+    TEST_TRUE(runner, CB_Equals_Str(elem, "c", 1), "Pop");
+    TEST_INT_EQ(runner, VA_Get_Size(array), 1, "size after Pop");
     DECREF(elem);
 
     VA_Unshift(array, (Obj*)CB_newf("foo"));
     elem = (CharBuf*)CERTIFY(VA_Fetch(array, 0), CHARBUF);
-    TEST_TRUE(batch, CB_Equals_Str(elem, "foo", 3), "Unshift");
-    TEST_INT_EQ(batch, VA_Get_Size(array), 2, "size after Shift");
+    TEST_TRUE(runner, CB_Equals_Str(elem, "foo", 3), "Unshift");
+    TEST_INT_EQ(runner, VA_Get_Size(array), 2, "size after Shift");
 
     DECREF(array);
 }
 
 static void
-test_Delete(TestBatch *batch) {
+test_Delete(TestBatchRunner *runner) {
     VArray *wanted = VA_new(5);
     VArray *got    = VA_new(5);
     uint32_t i;
@@ -153,34 +147,34 @@ test_Delete(TestBatch *batch) {
     VA_Store(wanted, 4, (Obj*)CB_newf("4", i));
     DECREF(VA_Delete(got, 2));
     DECREF(VA_Delete(got, 3));
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got), "Delete");
+    TEST_TRUE(runner, VA_Equals(wanted, (Obj*)got), "Delete");
 
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_Resize(TestBatch *batch) {
+test_Resize(TestBatchRunner *runner) {
     VArray *array = VA_new(3);
     uint32_t i;
 
     for (i = 0; i < 2; i++) { VA_Push(array, (Obj*)CB_newf("%u32", i)); }
-    TEST_INT_EQ(batch, VA_Get_Capacity(array), 3, "Start with capacity 3");
+    TEST_INT_EQ(runner, VA_Get_Capacity(array), 3, "Start with capacity 3");
 
     VA_Resize(array, 4);
-    TEST_INT_EQ(batch, VA_Get_Size(array), 4, "Resize up");
-    TEST_INT_EQ(batch, VA_Get_Capacity(array), 4,
+    TEST_INT_EQ(runner, VA_Get_Size(array), 4, "Resize up");
+    TEST_INT_EQ(runner, VA_Get_Capacity(array), 4,
                 "Resize changes capacity");
 
     VA_Resize(array, 2);
-    TEST_INT_EQ(batch, VA_Get_Size(array), 2, "Resize down");
-    TEST_TRUE(batch, VA_Fetch(array, 2) == NULL, "Resize down zaps elem");
+    TEST_INT_EQ(runner, VA_Get_Size(array), 2, "Resize down");
+    TEST_TRUE(runner, VA_Fetch(array, 2) == NULL, "Resize down zaps elem");
 
     DECREF(array);
 }
 
 static void
-test_Excise(TestBatch *batch) {
+test_Excise(TestBatchRunner *runner) {
     VArray *wanted = VA_new(5);
     VArray *got    = VA_new(5);
 
@@ -190,7 +184,7 @@ test_Excise(TestBatch *batch) {
     }
 
     VA_Excise(got, 7, 1);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
+    TEST_TRUE(runner, VA_Equals(wanted, (Obj*)got),
               "Excise outside of range is no-op");
 
     VA_Excise(got, 2, 2);
@@ -198,18 +192,18 @@ test_Excise(TestBatch *batch) {
     DECREF(VA_Delete(wanted, 3));
     VA_Store(wanted, 2, VA_Delete(wanted, 4));
     VA_Resize(wanted, 3);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
+    TEST_TRUE(runner, VA_Equals(wanted, (Obj*)got),
               "Excise multiple elems");
 
     VA_Excise(got, 2, 2);
     VA_Resize(wanted, 2);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
+    TEST_TRUE(runner, VA_Equals(wanted, (Obj*)got),
               "Splicing too many elems truncates");
 
     VA_Excise(got, 0, 1);
     VA_Store(wanted, 0, VA_Delete(wanted, 1));
     VA_Resize(wanted, 1);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
+    TEST_TRUE(runner, VA_Equals(wanted, (Obj*)got),
               "Excise first elem");
 
     DECREF(got);
@@ -217,7 +211,7 @@ test_Excise(TestBatch *batch) {
 }
 
 static void
-test_Push_VArray(TestBatch *batch) {
+test_Push_VArray(TestBatchRunner *runner) {
     VArray *wanted  = VA_new(0);
     VArray *got     = VA_new(0);
     VArray *scratch = VA_new(0);
@@ -228,7 +222,7 @@ test_Push_VArray(TestBatch *batch) {
     for (i = 2; i < 4; i++) { VA_Push(scratch, (Obj*)CB_newf("%u32", i)); }
 
     VA_Push_VArray(got, scratch);
-    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got), "Push_VArray");
+    TEST_TRUE(runner, VA_Equals(wanted, (Obj*)got), "Push_VArray");
 
     DECREF(wanted);
     DECREF(got);
@@ -236,17 +230,17 @@ test_Push_VArray(TestBatch *batch) {
 }
 
 static void
-test_Slice(TestBatch *batch) {
+test_Slice(TestBatchRunner *runner) {
     VArray *array = VA_new(0);
     for (uint32_t i = 0; i < 10; i++) { VA_Push(array, (Obj*)CB_newf("%u32", i)); }
     {
         VArray *slice = VA_Slice(array, 0, 10);
-        TEST_TRUE(batch, VA_Equals(array, (Obj*)slice), "Slice entire array");
+        TEST_TRUE(runner, VA_Equals(array, (Obj*)slice), "Slice entire array");
         DECREF(slice);
     }
     {
         VArray *slice = VA_Slice(array, 0, 11);
-        TEST_TRUE(batch, VA_Equals(array, (Obj*)slice),
+        TEST_TRUE(runner, VA_Equals(array, (Obj*)slice),
             "Exceed length");
         DECREF(slice);
     }
@@ -254,26 +248,26 @@ test_Slice(TestBatch *batch) {
         VArray *wanted = VA_new(0);
         VA_Push(wanted, (Obj*)CB_newf("9"));
         VArray *slice = VA_Slice(array, 9, 11);
-        TEST_TRUE(batch, VA_Equals(slice, (Obj*)wanted),
+        TEST_TRUE(runner, VA_Equals(slice, (Obj*)wanted),
             "Exceed length, start near end");
         DECREF(slice);
         DECREF(wanted);
     }
     {
         VArray *slice = VA_Slice(array, 0, 0);
-        TEST_TRUE(batch, VA_Get_Size(slice) == 0, "empty slice");
+        TEST_TRUE(runner, VA_Get_Size(slice) == 0, "empty slice");
         DECREF(slice);
     }
     {
         VArray *slice = VA_Slice(array, 20, 1);
-        TEST_TRUE(batch, VA_Get_Size(slice) ==  0, "exceed offset");
+        TEST_TRUE(runner, VA_Get_Size(slice) ==  0, "exceed offset");
         DECREF(slice);
     }
     {
         VArray *wanted = VA_new(0);
         VA_Push(wanted, (Obj*)CB_newf("9"));
         VArray *slice = VA_Slice(array, 9, UINT32_MAX - 1);
-        TEST_TRUE(batch, VA_Get_Size(slice) == 1, "guard against overflow");
+        TEST_TRUE(runner, VA_Get_Size(slice) == 1, "guard against overflow");
         DECREF(slice);
         DECREF(wanted);
     }
@@ -281,7 +275,7 @@ test_Slice(TestBatch *batch) {
 }
 
 static void
-test_Clone_and_Shallow_Copy(TestBatch *batch) {
+test_Clone_and_Shallow_Copy(TestBatchRunner *runner) {
     VArray *array = VA_new(0);
     VArray *twin;
     uint32_t i;
@@ -290,14 +284,14 @@ test_Clone_and_Shallow_Copy(TestBatch *batch) {
         VA_Push(array, (Obj*)CB_newf("%u32", i));
     }
     twin = VA_Shallow_Copy(array);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)twin), "Shallow_Copy");
-    TEST_TRUE(batch, VA_Fetch(array, 1) == VA_Fetch(twin, 1),
+    TEST_TRUE(runner, VA_Equals(array, (Obj*)twin), "Shallow_Copy");
+    TEST_TRUE(runner, VA_Fetch(array, 1) == VA_Fetch(twin, 1),
               "Shallow_Copy doesn't clone elements");
     DECREF(twin);
 
     twin = VA_Clone(array);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)twin), "Clone");
-    TEST_TRUE(batch, VA_Fetch(array, 1) != VA_Fetch(twin, 1),
+    TEST_TRUE(runner, VA_Equals(array, (Obj*)twin), "Clone");
+    TEST_TRUE(runner, VA_Fetch(array, 1) != VA_Fetch(twin, 1),
               "Clone performs deep clone");
 
     DECREF(array);
@@ -305,7 +299,7 @@ test_Clone_and_Shallow_Copy(TestBatch *batch) {
 }
 
 static void
-test_Dump_and_Load(TestBatch *batch) {
+test_Dump_and_Load(TestBatchRunner *runner) {
     VArray *array = VA_new(0);
     Obj    *dump;
     VArray *loaded;
@@ -313,7 +307,7 @@ test_Dump_and_Load(TestBatch *batch) {
     VA_Push(array, (Obj*)S_new_cb("foo"));
     dump = (Obj*)VA_Dump(array);
     loaded = (VArray*)Obj_Load(dump, dump);
-    TEST_TRUE(batch, VA_Equals(array, (Obj*)loaded),
+    TEST_TRUE(runner, VA_Equals(array, (Obj*)loaded),
               "Dump => Load round trip");
 
     DECREF(array);
@@ -322,32 +316,32 @@ test_Dump_and_Load(TestBatch *batch) {
 }
 
 static void
-test_serialization(TestBatch *batch) {
+test_serialization(TestBatchRunner *runner) {
     VArray *array = VA_new(0);
     VArray *dupe;
     VA_Store(array, 1, (Obj*)CB_newf("foo"));
     VA_Store(array, 3, (Obj*)CB_newf("bar"));
     dupe = (VArray*)TestUtils_freeze_thaw((Obj*)array);
-    TEST_TRUE(batch, dupe && VA_Equals(array, (Obj*)dupe),
+    TEST_TRUE(runner, dupe && VA_Equals(array, (Obj*)dupe),
               "Round trip through FREEZE/THAW");
     DECREF(dupe);
     DECREF(array);
 }
 
 void
-TestVArray_run_tests(TestVArray *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Equals(batch);
-    test_Store_Fetch(batch);
-    test_Push_Pop_Shift_Unshift(batch);
-    test_Delete(batch);
-    test_Resize(batch);
-    test_Excise(batch);
-    test_Push_VArray(batch);
-    test_Slice(batch);
-    test_Clone_and_Shallow_Copy(batch);
-    test_Dump_and_Load(batch);
-    test_serialization(batch);
+TestVArray_run(TestVArray *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 45);
+    test_Equals(runner);
+    test_Store_Fetch(runner);
+    test_Push_Pop_Shift_Unshift(runner);
+    test_Delete(runner);
+    test_Resize(runner);
+    test_Excise(runner);
+    test_Push_VArray(runner);
+    test_Slice(runner);
+    test_Clone_and_Shallow_Copy(runner);
+    test_Dump_and_Load(runner);
+    test_serialization(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestVArray.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestVArray.cfh b/core/Clownfish/Test/TestVArray.cfh
index 478127a..735fccb 100644
--- a/core/Clownfish/Test/TestVArray.cfh
+++ b/core/Clownfish/Test/TestVArray.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::TestVArray
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestVArray*
-    new(TestFormatter *formatter);
-
-    inert TestVArray*
-    init(TestVArray *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestVArray *self);
+    Run(TestVArray *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/Util/TestAtomic.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestAtomic.c b/core/Clownfish/Test/Util/TestAtomic.c
index 6187198..d2cb408 100644
--- a/core/Clownfish/Test/Util/TestAtomic.c
+++ b/core/Clownfish/Test/Util/TestAtomic.c
@@ -20,52 +20,46 @@
 #include "Clownfish/Test/Util/TestAtomic.h"
 
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/Util/Atomic.h"
 #include "Clownfish/VTable.h"
 
 TestAtomic*
-TestAtomic_new(TestFormatter *formatter) {
-    TestAtomic *self = (TestAtomic*)VTable_Make_Obj(TESTATOMIC);
-    return TestAtomic_init(self, formatter);
-}
-
-TestAtomic*
-TestAtomic_init(TestAtomic *self, TestFormatter *formatter) {
-    return (TestAtomic*)TestBatch_init((TestBatch*)self, 6, formatter);
+TestAtomic_new() {
+    return (TestAtomic*)VTable_Make_Obj(TESTATOMIC);
 }
 
 static void
-test_cas_ptr(TestBatch *batch) {
+test_cas_ptr(TestBatchRunner *runner) {
     int    foo = 1;
     int    bar = 2;
     int   *foo_pointer = &foo;
     int   *bar_pointer = &bar;
     int   *target      = NULL;
 
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               Atomic_cas_ptr((void**)&target, NULL, foo_pointer),
               "cas_ptr returns true on success");
-    TEST_TRUE(batch, target == foo_pointer, "cas_ptr sets target");
+    TEST_TRUE(runner, target == foo_pointer, "cas_ptr sets target");
 
     target = NULL;
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                Atomic_cas_ptr((void**)&target, bar_pointer, foo_pointer),
                "cas_ptr returns false when it old_value doesn't match");
-    TEST_TRUE(batch, target == NULL,
+    TEST_TRUE(runner, target == NULL,
               "cas_ptr doesn't do anything to target when old_value doesn't match");
 
     target = foo_pointer;
-    TEST_TRUE(batch,
+    TEST_TRUE(runner,
               Atomic_cas_ptr((void**)&target, foo_pointer, bar_pointer),
               "cas_ptr from one value to another");
-    TEST_TRUE(batch, target == bar_pointer, "cas_ptr sets target");
+    TEST_TRUE(runner, target == bar_pointer, "cas_ptr sets target");
 }
 
 void
-TestAtomic_run_tests(TestAtomic *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_cas_ptr(batch);
+TestAtomic_run(TestAtomic *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
+    test_cas_ptr(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/Util/TestAtomic.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestAtomic.cfh b/core/Clownfish/Test/Util/TestAtomic.cfh
index 576eec9..2788342 100644
--- a/core/Clownfish/Test/Util/TestAtomic.cfh
+++ b/core/Clownfish/Test/Util/TestAtomic.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::Util::TestAtomic
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestAtomic*
-    new(TestFormatter *formatter);
-
-    inert TestAtomic*
-    init(TestAtomic *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestAtomic *self);
+    Run(TestAtomic *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/Util/TestMemory.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestMemory.c b/core/Clownfish/Test/Util/TestMemory.c
index 0c58b99..24c8ad3 100644
--- a/core/Clownfish/Test/Util/TestMemory.c
+++ b/core/Clownfish/Test/Util/TestMemory.c
@@ -21,23 +21,17 @@
 #include "Clownfish/Test/Util/TestMemory.h"
 
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/VTable.h"
 
 TestMemory*
-TestMemory_new(TestFormatter *formatter) {
-    TestMemory *self = (TestMemory*)VTable_Make_Obj(TESTMEMORY);
-    return TestMemory_init(self, formatter);
-}
-
-TestMemory*
-TestMemory_init(TestMemory *self, TestFormatter *formatter) {
-    return (TestMemory*)TestBatch_init((TestBatch*)self, 30, formatter);
+TestMemory_new() {
+    return (TestMemory*)VTable_Make_Obj(TESTMEMORY);
 }
 
 static void
-test_oversize__growth_rate(TestBatch *batch) {
+test_oversize__growth_rate(TestBatchRunner *runner) {
     bool     success             = true;
     uint64_t size                = 0;
     double   growth_count        = 0;
@@ -47,7 +41,7 @@ test_oversize__growth_rate(TestBatch *batch) {
         uint64_t next_size = Memory_oversize((size_t)size + 1, sizeof(void*));
         if (next_size < size) {
             success = false;
-            FAIL(batch, "Asked for %" PRId64 ", got smaller amount %" PRId64,
+            FAIL(runner, "Asked for %" PRId64 ", got smaller amount %" PRId64,
                  size + 1, next_size);
             break;
         }
@@ -58,7 +52,7 @@ test_oversize__growth_rate(TestBatch *batch) {
             double sum = growth_rate + (growth_count - 1) * average_growth_rate;
             average_growth_rate = sum / growth_count;
             if (average_growth_rate < 1.1) {
-                FAIL(batch, "Average growth rate dropped below 1.1x: %f",
+                FAIL(runner, "Average growth rate dropped below 1.1x: %f",
                      average_growth_rate);
                 success = false;
                 break;
@@ -66,9 +60,9 @@ test_oversize__growth_rate(TestBatch *batch) {
         }
         size = next_size;
     }
-    TEST_TRUE(batch, growth_count > 0, "Grew %f times", growth_count);
+    TEST_TRUE(runner, growth_count > 0, "Grew %f times", growth_count);
     if (success) {
-        TEST_TRUE(batch, average_growth_rate > 1.1,
+        TEST_TRUE(runner, average_growth_rate > 1.1,
                   "Growth rate of oversize() averages above 1.1: %.3f",
                   average_growth_rate);
     }
@@ -76,26 +70,26 @@ test_oversize__growth_rate(TestBatch *batch) {
     for (int minimum = 1; minimum < 8; minimum++) {
         uint64_t next_size = Memory_oversize(minimum, sizeof(void*));
         double growth_rate = U64_TO_DOUBLE(next_size) / (double)minimum;
-        TEST_TRUE(batch, growth_rate > 1.2,
+        TEST_TRUE(runner, growth_rate > 1.2,
                   "Growth rate is higher for smaller arrays (%d, %.3f)", minimum,
                   growth_rate);
     }
 }
 
 static void
-test_oversize__ceiling(TestBatch *batch) {
+test_oversize__ceiling(TestBatchRunner *runner) {
     for (int width = 0; width < 10; width++) {
         size_t size = Memory_oversize(SIZE_MAX, width);
-        TEST_TRUE(batch, size == SIZE_MAX,
+        TEST_TRUE(runner, size == SIZE_MAX,
                   "Memory_oversize hits ceiling at SIZE_MAX (width %d)", width);
         size = Memory_oversize(SIZE_MAX - 1, width);
-        TEST_TRUE(batch, size == SIZE_MAX,
+        TEST_TRUE(runner, size == SIZE_MAX,
                   "Memory_oversize hits ceiling at SIZE_MAX (width %d)", width);
     }
 }
 
 static void
-test_oversize__rounding(TestBatch *batch) {
+test_oversize__rounding(TestBatchRunner *runner) {
     int widths[] = { 1, 2, 4, 0 };
 
     for (int width_tick = 0; widths[width_tick] != 0; width_tick++) {
@@ -104,21 +98,21 @@ test_oversize__rounding(TestBatch *batch) {
             size_t size = Memory_oversize(i, width);
             size_t bytes = size * width;
             if (bytes % sizeof(void*) != 0) {
-                FAIL(batch, "Rounding failure for %d, width %d",
+                FAIL(runner, "Rounding failure for %d, width %d",
                      i, width);
                 return;
             }
         }
     }
-    PASS(batch, "Round allocations up to the size of a pointer");
+    PASS(runner, "Round allocations up to the size of a pointer");
 }
 
 void
-TestMemory_run_tests(TestMemory *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_oversize__growth_rate(batch);
-    test_oversize__ceiling(batch);
-    test_oversize__rounding(batch);
+TestMemory_run(TestMemory *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 30);
+    test_oversize__growth_rate(runner);
+    test_oversize__ceiling(runner);
+    test_oversize__rounding(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/Util/TestMemory.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestMemory.cfh b/core/Clownfish/Test/Util/TestMemory.cfh
index 6426935..d0b5803 100644
--- a/core/Clownfish/Test/Util/TestMemory.cfh
+++ b/core/Clownfish/Test/Util/TestMemory.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::Util::TestMemory
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestMemory*
-    new(TestFormatter *formatter);
-
-    inert TestMemory*
-    init(TestMemory *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestMemory *self);
+    Run(TestMemory *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/Util/TestNumberUtils.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestNumberUtils.c b/core/Clownfish/Test/Util/TestNumberUtils.c
index 04c79f0..0ae476d 100644
--- a/core/Clownfish/Test/Util/TestNumberUtils.c
+++ b/core/Clownfish/Test/Util/TestNumberUtils.c
@@ -24,25 +24,19 @@
 
 #include "Clownfish/Err.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/Util/NumberUtils.h"
 #include "Clownfish/VTable.h"
 
 TestNumberUtils*
-TestNumUtil_new(TestFormatter *formatter) {
-    TestNumberUtils *self = (TestNumberUtils*)VTable_Make_Obj(TESTNUMBERUTILS);
-    return TestNumUtil_init(self, formatter);
-}
-
-TestNumberUtils*
-TestNumUtil_init(TestNumberUtils *self, TestFormatter *formatter) {
-    return (TestNumberUtils*)TestBatch_init((TestBatch*)self, 1196, formatter);
+TestNumUtil_new() {
+    return (TestNumberUtils*)VTable_Make_Obj(TESTNUMBERUTILS);
 }
 
 static void
-test_u1(TestBatch *batch) {
+test_u1(TestBatchRunner *runner) {
     size_t    count   = 64;
     uint64_t *ints    = TestUtils_random_u64s(NULL, count, 0, 2);
     size_t    amount  = count / 8;
@@ -52,7 +46,7 @@ test_u1(TestBatch *batch) {
         if (ints[i]) { NumUtil_u1set(bits, i); }
     }
     for (size_t i = 0; i < count; i++) {
-        TEST_INT_EQ(batch, NumUtil_u1get(bits, i), (long)ints[i],
+        TEST_INT_EQ(runner, NumUtil_u1get(bits, i), (long)ints[i],
                     "u1 set/get");
     }
 
@@ -60,7 +54,7 @@ test_u1(TestBatch *batch) {
         NumUtil_u1flip(bits, i);
     }
     for (size_t i = 0; i < count; i++) {
-        TEST_INT_EQ(batch, NumUtil_u1get(bits, i), !ints[i], "u1 flip");
+        TEST_INT_EQ(runner, NumUtil_u1get(bits, i), !ints[i], "u1 flip");
     }
 
     FREEMEM(bits);
@@ -68,7 +62,7 @@ test_u1(TestBatch *batch) {
 }
 
 static void
-test_u2(TestBatch *batch) {
+test_u2(TestBatchRunner *runner) {
     size_t    count = 32;
     uint64_t *ints = TestUtils_random_u64s(NULL, count, 0, 4);
     uint8_t  *bits = (uint8_t*)CALLOCATE((count / 4), sizeof(uint8_t));
@@ -77,7 +71,7 @@ test_u2(TestBatch *batch) {
         NumUtil_u2set(bits, i, (uint8_t)ints[i]);
     }
     for (size_t i = 0; i < count; i++) {
-        TEST_INT_EQ(batch, NumUtil_u2get(bits, i), (long)ints[i], "u2");
+        TEST_INT_EQ(runner, NumUtil_u2get(bits, i), (long)ints[i], "u2");
     }
 
     FREEMEM(bits);
@@ -85,7 +79,7 @@ test_u2(TestBatch *batch) {
 }
 
 static void
-test_u4(TestBatch *batch) {
+test_u4(TestBatchRunner *runner) {
     size_t    count = 128;
     uint64_t *ints  = TestUtils_random_u64s(NULL, count, 0, 16);
     uint8_t  *bits  = (uint8_t*)CALLOCATE((count / 2), sizeof(uint8_t));
@@ -94,7 +88,7 @@ test_u4(TestBatch *batch) {
         NumUtil_u4set(bits, i, (uint8_t)ints[i]);
     }
     for (size_t i = 0; i < count; i++) {
-        TEST_INT_EQ(batch, NumUtil_u4get(bits, i), (long)ints[i], "u4");
+        TEST_INT_EQ(runner, NumUtil_u4get(bits, i), (long)ints[i], "u4");
     }
 
     FREEMEM(bits);
@@ -102,7 +96,7 @@ test_u4(TestBatch *batch) {
 }
 
 static void
-test_c32(TestBatch *batch) {
+test_c32(TestBatchRunner *runner) {
     uint64_t  mins[]   = { 0,   0x4000 - 100, (uint32_t)INT32_MAX - 100, UINT32_MAX - 10 };
     uint64_t  limits[] = { 500, 0x4000 + 100, (uint32_t)INT32_MAX + 100, UINT32_MAX      };
     uint32_t  set_num;
@@ -125,44 +119,44 @@ test_c32(TestBatch *batch) {
         target = encoded;
         skip   = encoded;
         for (size_t i = 0; i < count; i++) {
-            TEST_INT_EQ(batch, NumUtil_decode_c32(&target), (long)ints[i],
+            TEST_INT_EQ(runner, NumUtil_decode_c32(&target), (long)ints[i],
                         "c32 %lu", (long)ints[i]);
             NumUtil_skip_cint(&skip);
             if (target > limit) { THROW(ERR, "overrun"); }
         }
-        TEST_TRUE(batch, skip == target, "skip %lu == %lu",
+        TEST_TRUE(runner, skip == target, "skip %lu == %lu",
                   (unsigned long)skip, (unsigned long)target);
 
         target = encoded;
         for (size_t i = 0; i < count; i++) {
             NumUtil_encode_padded_c32((uint32_t)ints[i], &target);
         }
-        TEST_TRUE(batch, target == limit,
+        TEST_TRUE(runner, target == limit,
                   "padded c32 uses 5 bytes (%lu == %lu)", (unsigned long)target,
                   (unsigned long)limit);
         target = encoded;
         skip   = encoded;
         for (size_t i = 0; i < count; i++) {
-            TEST_INT_EQ(batch, NumUtil_decode_c32(&target), (long)ints[i],
+            TEST_INT_EQ(runner, NumUtil_decode_c32(&target), (long)ints[i],
                         "padded c32 %lu", (long)ints[i]);
             NumUtil_skip_cint(&skip);
             if (target > limit) { THROW(ERR, "overrun"); }
         }
-        TEST_TRUE(batch, skip == target, "skip padded %lu == %lu",
+        TEST_TRUE(runner, skip == target, "skip padded %lu == %lu",
                   (unsigned long)skip, (unsigned long)target);
     }
 
     target = encoded;
     NumUtil_encode_c32(UINT32_MAX, &target);
     target = encoded;
-    TEST_INT_EQ(batch, NumUtil_decode_c32(&target), UINT32_MAX, "c32 UINT32_MAX");
+    TEST_INT_EQ(runner, NumUtil_decode_c32(&target), UINT32_MAX, "c32 UINT32_MAX");
 
     FREEMEM(encoded);
     FREEMEM(ints);
 }
 
 static void
-test_c64(TestBatch *batch) {
+test_c64(TestBatchRunner *runner) {
     uint64_t  mins[]    = { 0,   0x4000 - 100, (uint64_t)UINT32_MAX - 100,  UINT64_MAX - 10 };
     uint64_t  limits[]  = { 500, 0x4000 + 100, (uint64_t)UINT32_MAX + 1000, UINT64_MAX      };
     uint32_t  set_num;
@@ -186,12 +180,12 @@ test_c64(TestBatch *batch) {
         skip   = encoded;
         for (size_t i = 0; i < count; i++) {
             uint64_t got = NumUtil_decode_c64(&target);
-            TEST_TRUE(batch, got == ints[i],
+            TEST_TRUE(runner, got == ints[i],
                       "c64 %" PRIu64 " == %" PRIu64, got, ints[i]);
             if (target > limit) { THROW(ERR, "overrun"); }
             NumUtil_skip_cint(&skip);
         }
-        TEST_TRUE(batch, skip == target, "skip %lu == %lu",
+        TEST_TRUE(runner, skip == target, "skip %lu == %lu",
                   (unsigned long)skip, (unsigned long)target);
     }
 
@@ -200,14 +194,14 @@ test_c64(TestBatch *batch) {
     target = encoded;
 
     uint64_t got = NumUtil_decode_c64(&target);
-    TEST_TRUE(batch, got == UINT64_MAX, "c64 UINT64_MAX");
+    TEST_TRUE(runner, got == UINT64_MAX, "c64 UINT64_MAX");
 
     FREEMEM(encoded);
     FREEMEM(ints);
 }
 
 static void
-test_bigend_u16(TestBatch *batch) {
+test_bigend_u16(TestBatchRunner *runner) {
     size_t    count     = 32;
     uint64_t *ints      = TestUtils_random_u64s(NULL, count, 0, UINT16_MAX + 1);
     size_t    amount    = (count + 1) * sizeof(uint16_t);
@@ -222,21 +216,21 @@ test_bigend_u16(TestBatch *batch) {
     target = encoded;
     for (size_t i = 0; i < count; i++) {
         uint16_t got = NumUtil_decode_bigend_u16(target);
-        TEST_INT_EQ(batch, got, (long)ints[i], "bigend u16");
+        TEST_INT_EQ(runner, got, (long)ints[i], "bigend u16");
         target += sizeof(uint16_t);
     }
 
     target = encoded;
     NumUtil_encode_bigend_u16(1, &target);
-    TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian u16");
-    TEST_INT_EQ(batch, encoded[1], 1, "Truly big-endian u16");
+    TEST_INT_EQ(runner, encoded[0], 0, "Truly big-endian u16");
+    TEST_INT_EQ(runner, encoded[1], 1, "Truly big-endian u16");
 
     FREEMEM(allocated);
     FREEMEM(ints);
 }
 
 static void
-test_bigend_u32(TestBatch *batch) {
+test_bigend_u32(TestBatchRunner *runner) {
     size_t    count     = 32;
     uint64_t *ints      = TestUtils_random_u64s(NULL, count, 0, UINT64_C(1) + UINT32_MAX);
     size_t    amount    = (count + 1) * sizeof(uint32_t);
@@ -251,21 +245,21 @@ test_bigend_u32(TestBatch *batch) {
     target = encoded;
     for (size_t i = 0; i < count; i++) {
         uint32_t got = NumUtil_decode_bigend_u32(target);
-        TEST_INT_EQ(batch, got, (long)ints[i], "bigend u32");
+        TEST_INT_EQ(runner, got, (long)ints[i], "bigend u32");
         target += sizeof(uint32_t);
     }
 
     target = encoded;
     NumUtil_encode_bigend_u32(1, &target);
-    TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian u32");
-    TEST_INT_EQ(batch, encoded[3], 1, "Truly big-endian u32");
+    TEST_INT_EQ(runner, encoded[0], 0, "Truly big-endian u32");
+    TEST_INT_EQ(runner, encoded[3], 1, "Truly big-endian u32");
 
     FREEMEM(allocated);
     FREEMEM(ints);
 }
 
 static void
-test_bigend_u64(TestBatch *batch) {
+test_bigend_u64(TestBatchRunner *runner) {
     size_t    count     = 32;
     uint64_t *ints      = TestUtils_random_u64s(NULL, count, 0, UINT64_MAX);
     size_t    amount    = (count + 1) * sizeof(uint64_t);
@@ -280,21 +274,21 @@ test_bigend_u64(TestBatch *batch) {
     target = encoded;
     for (size_t i = 0; i < count; i++) {
         uint64_t got = NumUtil_decode_bigend_u64(target);
-        TEST_TRUE(batch, got == ints[i], "bigend u64");
+        TEST_TRUE(runner, got == ints[i], "bigend u64");
         target += sizeof(uint64_t);
     }
 
     target = encoded;
     NumUtil_encode_bigend_u64(1, &target);
-    TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian");
-    TEST_INT_EQ(batch, encoded[7], 1, "Truly big-endian");
+    TEST_INT_EQ(runner, encoded[0], 0, "Truly big-endian");
+    TEST_INT_EQ(runner, encoded[7], 1, "Truly big-endian");
 
     FREEMEM(allocated);
     FREEMEM(ints);
 }
 
 static void
-test_bigend_f32(TestBatch *batch) {
+test_bigend_f32(TestBatchRunner *runner) {
     float    source[]  = { -1.3f, 0.0f, 100.2f };
     size_t   count     = 3;
     size_t   amount    = (count + 1) * sizeof(float);
@@ -309,18 +303,18 @@ test_bigend_f32(TestBatch *batch) {
     target = encoded;
     for (size_t i = 0; i < count; i++) {
         float got = NumUtil_decode_bigend_f32(target);
-        TEST_TRUE(batch, got == source[i], "bigend f32");
+        TEST_TRUE(runner, got == source[i], "bigend f32");
         target += sizeof(float);
     }
 
     target = encoded;
     NumUtil_encode_bigend_f32(-2.0f, &target);
-    TEST_INT_EQ(batch, (encoded[0] & 0x80), 0x80,
+    TEST_INT_EQ(runner, (encoded[0] & 0x80), 0x80,
                 "Truly big-endian (IEEE 754 sign bit set for negative number)");
-    TEST_INT_EQ(batch, encoded[0], 0xC0,
+    TEST_INT_EQ(runner, encoded[0], 0xC0,
                 "IEEE 754 representation of -2.0f, byte 0");
     for (size_t i = 1; i < sizeof(float); i++) {
-        TEST_INT_EQ(batch, encoded[i], 0,
+        TEST_INT_EQ(runner, encoded[i], 0,
                     "IEEE 754 representation of -2.0f, byte %d", (int)i);
     }
 
@@ -328,7 +322,7 @@ test_bigend_f32(TestBatch *batch) {
 }
 
 static void
-test_bigend_f64(TestBatch *batch) {
+test_bigend_f64(TestBatchRunner *runner) {
     double   source[]  = { -1.3, 0.0, 100.2 };
     size_t   count     = 3;
     size_t   amount    = (count + 1) * sizeof(double);
@@ -343,18 +337,18 @@ test_bigend_f64(TestBatch *batch) {
     target = encoded;
     for (size_t i = 0; i < count; i++) {
         double got = NumUtil_decode_bigend_f64(target);
-        TEST_TRUE(batch, got == source[i], "bigend f64");
+        TEST_TRUE(runner, got == source[i], "bigend f64");
         target += sizeof(double);
     }
 
     target = encoded;
     NumUtil_encode_bigend_f64(-2.0, &target);
-    TEST_INT_EQ(batch, (encoded[0] & 0x80), 0x80,
+    TEST_INT_EQ(runner, (encoded[0] & 0x80), 0x80,
                 "Truly big-endian (IEEE 754 sign bit set for negative number)");
-    TEST_INT_EQ(batch, encoded[0], 0xC0,
+    TEST_INT_EQ(runner, encoded[0], 0xC0,
                 "IEEE 754 representation of -2.0, byte 0");
     for (size_t i = 1; i < sizeof(double); i++) {
-        TEST_INT_EQ(batch, encoded[i], 0,
+        TEST_INT_EQ(runner, encoded[i], 0,
                     "IEEE 754 representation of -2.0, byte %d", (int)i);
     }
 
@@ -362,19 +356,19 @@ test_bigend_f64(TestBatch *batch) {
 }
 
 void
-TestNumUtil_run_tests(TestNumberUtils *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestNumUtil_run(TestNumberUtils *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1196);
     srand((unsigned int)time((time_t*)NULL));
-    test_u1(batch);
-    test_u2(batch);
-    test_u4(batch);
-    test_c32(batch);
-    test_c64(batch);
-    test_bigend_u16(batch);
-    test_bigend_u32(batch);
-    test_bigend_u64(batch);
-    test_bigend_f32(batch);
-    test_bigend_f64(batch);
+    test_u1(runner);
+    test_u2(runner);
+    test_u4(runner);
+    test_c32(runner);
+    test_c64(runner);
+    test_bigend_u16(runner);
+    test_bigend_u32(runner);
+    test_bigend_u64(runner);
+    test_bigend_f32(runner);
+    test_bigend_f64(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/Util/TestNumberUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestNumberUtils.cfh b/core/Clownfish/Test/Util/TestNumberUtils.cfh
index 1e4bacc..cd9e165 100644
--- a/core/Clownfish/Test/Util/TestNumberUtils.cfh
+++ b/core/Clownfish/Test/Util/TestNumberUtils.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::Util::TestNumberUtils cnick TestNumUtil
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNumberUtils*
-    new(TestFormatter *formatter);
-
-    inert TestNumberUtils*
-    init(TestNumberUtils *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestNumberUtils *self);
+    Run(TestNumberUtils *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/Util/TestStringHelper.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestStringHelper.c b/core/Clownfish/Test/Util/TestStringHelper.c
index 0ca46e9..7b24f1d 100644
--- a/core/Clownfish/Test/Util/TestStringHelper.c
+++ b/core/Clownfish/Test/Util/TestStringHelper.c
@@ -24,7 +24,7 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/Util/StringHelper.h"
 #include "Clownfish/VTable.h"
@@ -36,14 +36,8 @@
  */
 #define TRAIL_OK(n) (n >= 0x80 && n <= 0xBF)
 TestStringHelper*
-TestStrHelp_new(TestFormatter *formatter) {
-    TestStringHelper *self = (TestStringHelper*)VTable_Make_Obj(TESTSTRINGHELPER);
-    return TestStrHelp_init(self, formatter);
-}
-
-TestStringHelper*
-TestStrHelp_init(TestStringHelper *self, TestFormatter *formatter) {
-    return (TestStringHelper*)TestBatch_init((TestBatch*)self, 41, formatter);
+TestStrHelp_new() {
+    return (TestStringHelper*)VTable_Make_Obj(TESTSTRINGHELPER);
 }
 
 static bool
@@ -136,35 +130,35 @@ S_utf8_valid_alt(const char *maybe_utf8, size_t size) {
 }
 
 static void
-test_overlap(TestBatch *batch) {
+test_overlap(TestBatchRunner *runner) {
     int32_t result;
     result = StrHelp_overlap("", "", 0, 0);
-    TEST_INT_EQ(batch, result, 0, "two empty strings");
+    TEST_INT_EQ(runner, result, 0, "two empty strings");
     result = StrHelp_overlap("", "foo", 0, 3);
-    TEST_INT_EQ(batch, result, 0, "first string is empty");
+    TEST_INT_EQ(runner, result, 0, "first string is empty");
     result = StrHelp_overlap("foo", "", 3, 0);
-    TEST_INT_EQ(batch, result, 0, "second string is empty");
+    TEST_INT_EQ(runner, result, 0, "second string is empty");
     result = StrHelp_overlap("foo", "foo", 3, 3);
-    TEST_INT_EQ(batch, result, 3, "equal strings");
+    TEST_INT_EQ(runner, result, 3, "equal strings");
     result = StrHelp_overlap("foo bar", "foo", 7, 3);
-    TEST_INT_EQ(batch, result, 3, "first string is longer");
+    TEST_INT_EQ(runner, result, 3, "first string is longer");
     result = StrHelp_overlap("foo", "foo bar", 3, 7);
-    TEST_INT_EQ(batch, result, 3, "second string is longer");
+    TEST_INT_EQ(runner, result, 3, "second string is longer");
 }
 
 
 static void
-test_to_base36(TestBatch *batch) {
+test_to_base36(TestBatchRunner *runner) {
     char buffer[StrHelp_MAX_BASE36_BYTES];
     StrHelp_to_base36(UINT64_MAX, buffer);
-    TEST_STR_EQ(batch, "3w5e11264sgsf", buffer, "base36 UINT64_MAX");
+    TEST_STR_EQ(runner, "3w5e11264sgsf", buffer, "base36 UINT64_MAX");
     StrHelp_to_base36(1, buffer);
-    TEST_STR_EQ(batch, "1", buffer, "base36 1");
-    TEST_INT_EQ(batch, buffer[1], 0, "base36 NULL termination");
+    TEST_STR_EQ(runner, "1", buffer, "base36 1");
+    TEST_INT_EQ(runner, buffer[1], 0, "base36 NULL termination");
 }
 
 static void
-test_utf8_round_trip(TestBatch *batch) {
+test_utf8_round_trip(TestBatchRunner *runner) {
     uint32_t code_point;
     for (code_point = 0; code_point <= 0x10FFFF; code_point++) {
         char buffer[4];
@@ -194,109 +188,109 @@ test_utf8_round_trip(TestBatch *batch) {
         }
     }
     if (code_point == 0x110000) {
-        PASS(batch, "Successfully round tripped 0 - 0x10FFFF");
+        PASS(runner, "Successfully round tripped 0 - 0x10FFFF");
     }
     else {
-        FAIL(batch, "Failed round trip at 0x%.1X", (unsigned)code_point);
+        FAIL(runner, "Failed round trip at 0x%.1X", (unsigned)code_point);
     }
 }
 
 static void
-S_test_validity(TestBatch *batch, const char *content, size_t size,
+S_test_validity(TestBatchRunner *runner, const char *content, size_t size,
                 bool expected, const char *description) {
     bool sane = StrHelp_utf8_valid(content, size);
     bool double_check = S_utf8_valid_alt(content, size);
     if (sane != double_check) {
-        FAIL(batch, "Disagreement: %s", description);
+        FAIL(runner, "Disagreement: %s", description);
     }
     else {
-        TEST_TRUE(batch, sane == expected, "%s", description);
+        TEST_TRUE(runner, sane == expected, "%s", description);
     }
 }
 
 static void
-test_utf8_valid(TestBatch *batch) {
+test_utf8_valid(TestBatchRunner *runner) {
     // Musical symbol G clef:
     // Code point: U+1D11E
     // UTF-16:     0xD834 0xDD1E
     // UTF-8       0xF0 0x9D 0x84 0x9E
-    S_test_validity(batch, "\xF0\x9D\x84\x9E", 4, true,
+    S_test_validity(runner, "\xF0\x9D\x84\x9E", 4, true,
                     "Musical symbol G clef");
-    S_test_validity(batch, "\xED\xA0\xB4\xED\xB4\x9E", 6, false,
+    S_test_validity(runner, "\xED\xA0\xB4\xED\xB4\x9E", 6, false,
                     "G clef as UTF-8 encoded UTF-16 surrogates");
-    S_test_validity(batch, ".\xED\xA0\xB4.", 5, false,
+    S_test_validity(runner, ".\xED\xA0\xB4.", 5, false,
                     "Isolated high surrogate");
-    S_test_validity(batch, ".\xED\xB4\x9E.", 5, false,
+    S_test_validity(runner, ".\xED\xB4\x9E.", 5, false,
                     "Isolated low surrogate");
 
     // Shortest form.
-    S_test_validity(batch, ".\xC1\x9C.", 4, false,
+    S_test_validity(runner, ".\xC1\x9C.", 4, false,
                     "Non-shortest form ASCII backslash");
-    S_test_validity(batch, ".\xC0\xAF.", 4, false,
+    S_test_validity(runner, ".\xC0\xAF.", 4, false,
                     "Non-shortest form ASCII slash");
-    S_test_validity(batch, ".\xC0\x80.", 4, false,
+    S_test_validity(runner, ".\xC0\x80.", 4, false,
                     "Non-shortest form ASCII NUL character");
 
     // Range.
-    S_test_validity(batch, "\xF8\x88\x80\x80\x80", 5, false, "5-byte UTF-8");
+    S_test_validity(runner, "\xF8\x88\x80\x80\x80", 5, false, "5-byte UTF-8");
 
     // Bad continuations.
-    S_test_validity(batch, "\xE2\x98\xBA\xE2\x98\xBA", 6, true,
+    S_test_validity(runner, "\xE2\x98\xBA\xE2\x98\xBA", 6, true,
                     "SmileySmiley");
-    S_test_validity(batch, "\xE2\xBA\xE2\x98\xBA", 5, false,
+    S_test_validity(runner, "\xE2\xBA\xE2\x98\xBA", 5, false,
                     "missing first continuation byte");
-    S_test_validity(batch, "\xE2\x98\xE2\x98\xBA", 5, false,
+    S_test_validity(runner, "\xE2\x98\xE2\x98\xBA", 5, false,
                     "missing second continuation byte");
-    S_test_validity(batch, "\xE2\xE2\x98\xBA", 4, false,
+    S_test_validity(runner, "\xE2\xE2\x98\xBA", 4, false,
                     "missing both continuation bytes");
-    S_test_validity(batch, "\xBA\xE2\x98\xBA\xE2\xBA", 5, false,
+    S_test_validity(runner, "\xBA\xE2\x98\xBA\xE2\xBA", 5, false,
                     "missing first continuation byte (end)");
-    S_test_validity(batch, "\xE2\x98\xBA\xE2\x98", 5, false,
+    S_test_validity(runner, "\xE2\x98\xBA\xE2\x98", 5, false,
                     "missing second continuation byte (end)");
-    S_test_validity(batch, "\xE2\x98\xBA\xE2", 4, false,
+    S_test_validity(runner, "\xE2\x98\xBA\xE2", 4, false,
                     "missing both continuation bytes (end)");
-    S_test_validity(batch, "\xBA\xE2\x98\xBA", 4, false,
+    S_test_validity(runner, "\xBA\xE2\x98\xBA", 4, false,
                     "isolated continuation byte 0xBA");
-    S_test_validity(batch, "\x98\xE2\x98\xBA", 4, false,
+    S_test_validity(runner, "\x98\xE2\x98\xBA", 4, false,
                     "isolated continuation byte 0x98");
-    S_test_validity(batch, "\xE2\x98\xBA\xBA", 4, false,
+    S_test_validity(runner, "\xE2\x98\xBA\xBA", 4, false,
                     "isolated continuation byte 0xBA (end)");
-    S_test_validity(batch, "\xE2\x98\xBA\x98", 4, false,
+    S_test_validity(runner, "\xE2\x98\xBA\x98", 4, false,
                     "isolated continuation byte 0x98 (end)");
 }
 
 static void
-test_is_whitespace(TestBatch *batch) {
-    TEST_TRUE(batch, StrHelp_is_whitespace(' '), "space is whitespace");
-    TEST_TRUE(batch, StrHelp_is_whitespace('\n'), "newline is whitespace");
-    TEST_TRUE(batch, StrHelp_is_whitespace('\t'), "tab is whitespace");
-    TEST_TRUE(batch, StrHelp_is_whitespace('\v'),
+test_is_whitespace(TestBatchRunner *runner) {
+    TEST_TRUE(runner, StrHelp_is_whitespace(' '), "space is whitespace");
+    TEST_TRUE(runner, StrHelp_is_whitespace('\n'), "newline is whitespace");
+    TEST_TRUE(runner, StrHelp_is_whitespace('\t'), "tab is whitespace");
+    TEST_TRUE(runner, StrHelp_is_whitespace('\v'),
               "vertical tab is whitespace");
-    TEST_TRUE(batch, StrHelp_is_whitespace(0x180E),
+    TEST_TRUE(runner, StrHelp_is_whitespace(0x180E),
               "Mongolian vowel separator is whitespace");
-    TEST_FALSE(batch, StrHelp_is_whitespace('a'), "'a' isn't whitespace");
-    TEST_FALSE(batch, StrHelp_is_whitespace(0), "NULL isn't whitespace");
-    TEST_FALSE(batch, StrHelp_is_whitespace(0x263A),
+    TEST_FALSE(runner, StrHelp_is_whitespace('a'), "'a' isn't whitespace");
+    TEST_FALSE(runner, StrHelp_is_whitespace(0), "NULL isn't whitespace");
+    TEST_FALSE(runner, StrHelp_is_whitespace(0x263A),
                "Smiley isn't whitespace");
 }
 
 static void
-test_back_utf8_char(TestBatch *batch) {
+test_back_utf8_char(TestBatchRunner *runner) {
     char buffer[4];
     char *buf = buffer + 1;
     uint32_t len = StrHelp_encode_utf8_char(0x263A, buffer);
     char *end = buffer + len;
-    TEST_TRUE(batch, StrHelp_back_utf8_char(end, buffer) == buffer,
+    TEST_TRUE(runner, StrHelp_back_utf8_char(end, buffer) == buffer,
               "back_utf8_char");
-    TEST_TRUE(batch, StrHelp_back_utf8_char(end, buf) == NULL,
+    TEST_TRUE(runner, StrHelp_back_utf8_char(end, buf) == NULL,
               "back_utf8_char returns NULL rather than back up beyond start");
-    TEST_TRUE(batch, StrHelp_back_utf8_char(buffer, buffer) == NULL,
+    TEST_TRUE(runner, StrHelp_back_utf8_char(buffer, buffer) == NULL,
               "back_utf8_char returns NULL when end == start");
 }
 
 static void
-test_utf8proc_normalization(TestBatch *batch) {
-    SKIP(batch, "utf8proc can't handle control chars or Unicode non-chars");
+test_utf8proc_normalization(TestBatchRunner *runner) {
+    SKIP(runner, "utf8proc can't handle control chars or Unicode non-chars");
     return;
 
     for (int32_t i = 0; i < 100; i++) {
@@ -316,7 +310,7 @@ test_utf8proc_normalization(TestBatch *batch) {
             if (!json) {
                 json = CB_newf("[failed to encode]");
             }
-            FAIL(batch, "Failed to normalize: %s", CB_Get_Ptr8(json));
+            FAIL(runner, "Failed to normalize: %s", CB_Get_Ptr8(json));
             DECREF(json);
             DECREF(source);
             return;
@@ -338,23 +332,23 @@ test_utf8proc_normalization(TestBatch *batch) {
         free(normalized);
         DECREF(source);
         if (comparison != 0) {
-            FAIL(batch, "Not fully normalized");
+            FAIL(runner, "Not fully normalized");
             return;
         }
     }
-    PASS(batch, "Normalization successful.");
+    PASS(runner, "Normalization successful.");
 }
 
 void
-TestStrHelp_run_tests(TestStringHelper *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_overlap(batch);
-    test_to_base36(batch);
-    test_utf8_round_trip(batch);
-    test_utf8_valid(batch);
-    test_is_whitespace(batch);
-    test_back_utf8_char(batch);
-    test_utf8proc_normalization(batch);
+TestStrHelp_run(TestStringHelper *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 41);
+    test_overlap(runner);
+    test_to_base36(runner);
+    test_utf8_round_trip(runner);
+    test_utf8_valid(runner);
+    test_is_whitespace(runner);
+    test_back_utf8_char(runner);
+    test_utf8proc_normalization(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/Util/TestStringHelper.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestStringHelper.cfh b/core/Clownfish/Test/Util/TestStringHelper.cfh
index 219ec81..0f8351a 100644
--- a/core/Clownfish/Test/Util/TestStringHelper.cfh
+++ b/core/Clownfish/Test/Util/TestStringHelper.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::Util::TestStringHelper cnick TestStrHelp
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestStringHelper*
-    new(TestFormatter *formatter);
-
-    inert TestStringHelper*
-    init(TestStringHelper *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestStringHelper *self);
+    Run(TestStringHelper *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestBatch.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestBatch.c b/core/Clownfish/TestHarness/TestBatch.c
deleted file mode 100644
index 486e967..0000000
--- a/core/Clownfish/TestHarness/TestBatch.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
-#define C_CFISH_TESTBATCH
-#define CFISH_USE_SHORT_NAMES
-#define LUCY_USE_SHORT_NAMES
-#include "Clownfish/TestHarness/TestBatch.h"
-#include "Clownfish/CharBuf.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
-#include "Clownfish/VArray.h"
-#include "Clownfish/VTable.h"
-
-struct try_run_tests_context {
-    TestBatch *batch;
-};
-
-static void
-S_try_run_tests(void *context);
-
-static bool
-S_vtest_true(TestBatch *self, bool condition, const char *pattern,
-             va_list args);
-
-TestBatch*
-TestBatch_new(uint32_t num_planned, TestFormatter *formatter) {
-    TestBatch *self = (TestBatch*)VTable_Make_Obj(TESTBATCH);
-    return TestBatch_init(self, num_planned, formatter);
-}
-
-TestBatch*
-TestBatch_init(TestBatch *self, uint32_t num_planned,
-               TestFormatter *formatter) {
-    // Assign.
-    self->num_planned = num_planned;
-    self->formatter   = (TestFormatter*)INCREF(formatter);
-
-    // Initialize.
-    self->test_num    = 0;
-    self->num_passed  = 0;
-    self->num_failed  = 0;
-    self->num_skipped = 0;
-
-    return self;
-}
-
-void
-TestBatch_destroy(TestBatch *self) {
-    DECREF(self->formatter);
-    SUPER_DESTROY(self, TESTBATCH);
-}
-
-bool
-TestBatch_run(TestBatch *self) {
-    TestFormatter_Batch_Prologue(self->formatter, self);
-
-    struct try_run_tests_context args;
-    args.batch = self;
-    Err *err = Err_trap(S_try_run_tests, &args);
-
-    bool failed = false;
-    if (err) {
-        failed = true;
-        CharBuf *mess = Err_Get_Mess(err);
-        INCREF(mess);
-        Err_warn_mess(mess);
-    }
-    if (self->num_failed > 0) {
-        failed = true;
-        TestFormatter_batch_comment(self->formatter, "%d/%d tests failed.\n",
-                                    self->num_failed, self->test_num);
-    }
-    if (self->test_num != self->num_planned) {
-        failed = true;
-        TestFormatter_batch_comment(self->formatter,
-                                    "Bad plan: You planned %d tests but ran"
-                                    " %d.\n",
-                                    self->num_planned, self->test_num);
-    }
-
-    return !failed;
-}
-
-static void
-S_try_run_tests(void *context) {
-    struct try_run_tests_context *args
-        = (struct try_run_tests_context*)context;
-    TestBatch_Run_Tests(args->batch);
-}
-
-uint32_t
-TestBatch_get_num_planned(TestBatch *self) {
-    return self->num_planned;
-}
-
-uint32_t
-TestBatch_get_num_tests(TestBatch *self) {
-    return self->test_num;
-}
-
-uint32_t
-TestBatch_get_num_failed(TestBatch *self) {
-    return self->num_failed;
-}
-
-bool
-TestBatch_test_true(void *vself, bool condition, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_True((TestBatch*)vself, condition,
-                                         pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_test_false(void *vself, bool condition, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_False((TestBatch*)vself, condition,
-                                          pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_test_int_equals(void *vself, long got, long expected,
-                          const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_Int_Equals((TestBatch*)vself, got,
-                                               expected, pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_test_float_equals(void *vself, double got, double expected,
-                            const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_Float_Equals((TestBatch*)vself, got,
-                                                 expected, pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_test_string_equals(void *vself, const char *got,
-                             const char *expected, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_String_Equals((TestBatch*)vself, got,
-                                                  expected, pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_pass(void *vself, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VPass((TestBatch*)vself, pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_fail(void *vself, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VFail((TestBatch*)vself, pattern, args);
-    va_end(args);
-    return result;
-}
-
-void
-TestBatch_skip(void *vself, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    TestBatch_VSkip((TestBatch*)vself, pattern, args);
-    va_end(args);
-}
-
-bool
-TestBatch_vtest_true(TestBatch *self, bool condition, const char *pattern,
-                     va_list args) {
-    return S_vtest_true(self, condition, pattern, args);
-}
-
-bool
-TestBatch_vtest_false(TestBatch *self, bool condition,
-                      const char *pattern, va_list args) {
-    return S_vtest_true(self, !condition, pattern, args);
-}
-
-bool
-TestBatch_vtest_int_equals(TestBatch *self, long got, long expected,
-                           const char *pattern, va_list args) {
-    bool pass = (got == expected);
-    S_vtest_true(self, pass, pattern, args);
-    if (!pass) {
-        TestFormatter_test_comment(self->formatter,
-                                   "Expected '%ld', got '%ld'.\n",
-                                   expected, got);
-    }
-    return pass;
-}
-
-bool
-TestBatch_vtest_float_equals(TestBatch *self, double got, double expected,
-                             const char *pattern, va_list args) {
-    double relative_error = got / expected - 1.0;
-    bool   pass           = (fabs(relative_error) < 1e-6);
-    S_vtest_true(self, pass, pattern, args);
-    if (!pass) {
-        TestFormatter_test_comment(self->formatter,
-                                   "Expected '%e', got '%e'.\n",
-                                   expected, got);
-    }
-    return pass;
-}
-
-bool
-TestBatch_vtest_string_equals(TestBatch *self, const char *got,
-                              const char *expected, const char *pattern,
-                              va_list args) {
-    bool pass = (strcmp(got, expected) == 0);
-    S_vtest_true(self, pass, pattern, args);
-    if (!pass) {
-        TestFormatter_test_comment(self->formatter,
-                                   "Expected '%s', got '%s'.\n",
-                                   expected, got);
-    }
-    return pass;
-}
-
-bool
-TestBatch_vpass(TestBatch *self, const char *pattern, va_list args) {
-    return S_vtest_true(self, true, pattern, args);
-}
-
-bool
-TestBatch_vfail(TestBatch *self, const char *pattern, va_list args) {
-    return S_vtest_true(self, false, pattern, args);
-}
-
-void
-TestBatch_vskip(TestBatch *self, const char *pattern, va_list args) {
-    self->test_num++;
-    // TODO: Add a VTest_Skip method to TestFormatter
-    TestFormatter_VTest_Result(self->formatter, true, self->test_num,
-                               pattern, args);
-    self->num_skipped++;
-}
-
-static bool
-S_vtest_true(TestBatch* self, bool condition, const char *pattern,
-             va_list args) {
-    // Increment test number.
-    self->test_num++;
-
-    if (condition) {
-        self->num_passed++;
-    }
-    else {
-        self->num_failed++;
-    }
-
-    TestFormatter_VTest_Result(self->formatter, condition, self->test_num,
-                               pattern, args);
-
-    return condition;
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestBatch.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestBatch.cfh b/core/Clownfish/TestHarness/TestBatch.cfh
index cf82286..21b1117 100644
--- a/core/Clownfish/TestHarness/TestBatch.cfh
+++ b/core/Clownfish/TestHarness/TestBatch.cfh
@@ -16,105 +16,13 @@
 
 parcel Clownfish;
 
+/** Abstract base class for test modules.
+ */
 abstract class Clownfish::TestHarness::TestBatch inherits Clownfish::Obj {
-    TestFormatter *formatter;
-    uint32_t       test_num;
-    uint32_t       num_planned;
-    uint32_t       num_passed;
-    uint32_t       num_failed;
-    uint32_t       num_skipped;
-
-    inert incremented TestBatch*
-    new(uint32_t num_planned, TestFormatter *formatter);
-
-    inert TestBatch*
-    init(TestBatch *self, uint32_t num_planned, TestFormatter *formatter);
-
-    public void
-    Destroy(TestBatch *self);
-
-    /** Run the test batch and print test output and diagnosis.
-     *
-     * @return true if the test batch passed.
-     */
-    bool
-    Run(TestBatch *self);
-
     /** Run the tests of the test batch.
      */
     abstract void
-    Run_Tests(TestBatch *self);
-
-    /** Return the number of tests planned.
-     */
-    uint32_t
-    Get_Num_Planned(TestBatch *self);
-
-    /** Return the number of tests run.
-     */
-    uint32_t
-    Get_Num_Tests(TestBatch *self);
-
-    /** Return the number of failed tests.
-     */
-    uint32_t
-    Get_Num_Failed(TestBatch *self);
-
-    inert bool
-    test_true(void *vself, bool condition, const char *pattern, ...);
-
-    inert bool
-    test_false(void *vself, bool condition, const char *pattern, ...);
-
-    inert bool
-    test_int_equals(void *vself, long got, long expected,
-                    const char *pattern, ...);
-
-    inert bool
-    test_float_equals(void *vself, double got, double expected,
-                      const char *pattern, ...);
-
-    inert bool
-    test_string_equals(void *vself, const char *got, const char *expected,
-                       const char *pattern, ...);
-
-    inert bool
-    pass(void *vself, const char *pattern, ...);
-
-    inert bool
-    fail(void *vself, const char *pattern, ...);
-
-    inert void
-    skip(void *vself, const char *pattern, ...);
-
-    bool
-    VTest_True(TestBatch *self, bool condition, const char *pattern,
-               va_list args);
-
-    bool
-    VTest_False(TestBatch *self, bool condition, const char *pattern,
-                va_list args);
-
-    bool
-    VTest_Int_Equals(TestBatch *self, long got, long expected,
-                     const char *pattern, va_list args);
-
-    bool
-    VTest_Float_Equals(TestBatch *self, double got, double expected,
-                       const char *pattern, va_list args);
-
-    bool
-    VTest_String_Equals(TestBatch *self, const char *got, const char *expected,
-                       const char *pattern, va_list args);
-
-    bool
-    VPass(TestBatch *self, const char *pattern, va_list args);
-
-    bool
-    VFail(TestBatch *self, const char *pattern, va_list args);
-
-    void
-    VSkip(TestBatch *self, const char *pattern, va_list args);
+    Run(TestBatch *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestBatchRunner.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestBatchRunner.c b/core/Clownfish/TestHarness/TestBatchRunner.c
new file mode 100644
index 0000000..2263d0d
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestBatchRunner.c
@@ -0,0 +1,308 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#define C_CFISH_TESTBATCHRUNNER
+#define CFISH_USE_SHORT_NAMES
+#define LUCY_USE_SHORT_NAMES
+
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/VArray.h"
+#include "Clownfish/VTable.h"
+
+struct try_run_tests_context {
+    TestBatchRunner *runner;
+    TestBatch       *batch;
+};
+
+static void
+S_try_run_tests(void *context);
+
+static bool
+S_vtest_true(TestBatchRunner *self, bool condition, const char *pattern,
+             va_list args);
+
+TestBatchRunner*
+TestBatchRunner_new(TestFormatter *formatter) {
+    TestBatchRunner *self = (TestBatchRunner*)VTable_Make_Obj(TESTBATCHRUNNER);
+    return TestBatchRunner_init(self, formatter);
+}
+
+TestBatchRunner*
+TestBatchRunner_init(TestBatchRunner *self, TestFormatter *formatter) {
+    // Assign.
+    self->formatter   = (TestFormatter*)INCREF(formatter);
+
+    // Initialize.
+    self->num_planned = 0;
+    self->test_num    = 0;
+    self->num_passed  = 0;
+    self->num_failed  = 0;
+    self->num_skipped = 0;
+
+    return self;
+}
+
+void
+TestBatchRunner_destroy(TestBatchRunner *self) {
+    DECREF(self->formatter);
+    SUPER_DESTROY(self, TESTBATCHRUNNER);
+}
+
+bool
+TestBatchRunner_run_batch(TestBatchRunner *self, TestBatch *batch) {
+    struct try_run_tests_context args;
+    args.runner = self;
+    args.batch  = batch;
+    Err *err = Err_trap(S_try_run_tests, &args);
+
+    bool failed = false;
+    if (err) {
+        failed = true;
+        CharBuf *mess = Err_Get_Mess(err);
+        INCREF(mess);
+        Err_warn_mess(mess);
+    }
+    if (self->num_failed > 0) {
+        failed = true;
+        TestFormatter_Batch_Comment(self->formatter, "%d/%d tests failed.\n",
+                                    self->num_failed, self->test_num);
+    }
+    if (self->test_num != self->num_planned) {
+        failed = true;
+        TestFormatter_Batch_Comment(self->formatter,
+                                    "Bad plan: You planned %d tests but ran"
+                                    " %d.\n",
+                                    self->num_planned, self->test_num);
+    }
+
+    return !failed;
+}
+
+static void
+S_try_run_tests(void *context) {
+    struct try_run_tests_context *args
+        = (struct try_run_tests_context*)context;
+    TestBatch_Run(args->batch, args->runner);
+}
+
+void
+TestBatchRunner_plan(TestBatchRunner *self, TestBatch *batch,
+                     uint32_t num_planned) {
+    self->num_planned = num_planned;
+    TestFormatter_Batch_Prologue(self->formatter, batch, num_planned);
+}
+
+uint32_t
+TestBatchRunner_get_num_planned(TestBatchRunner *self) {
+    return self->num_planned;
+}
+
+uint32_t
+TestBatchRunner_get_num_tests(TestBatchRunner *self) {
+    return self->test_num;
+}
+
+uint32_t
+TestBatchRunner_get_num_failed(TestBatchRunner *self) {
+    return self->num_failed;
+}
+
+bool
+TestBatchRunner_test_true(TestBatchRunner *self, bool condition,
+                          const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatchRunner_VTest_True(self, condition, pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatchRunner_test_false(TestBatchRunner *self, bool condition,
+                           const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatchRunner_VTest_False(self, condition, pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatchRunner_test_int_equals(TestBatchRunner *self, long got, long expected,
+                                const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatchRunner_VTest_Int_Equals(self, got, expected,
+                                                   pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatchRunner_test_float_equals(TestBatchRunner *self, double got,
+                                  double expected, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatchRunner_VTest_Float_Equals(self, got, expected,
+                                                     pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatchRunner_test_string_equals(TestBatchRunner *self, const char *got,
+                                   const char *expected, const char *pattern,
+                                   ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatchRunner_VTest_String_Equals(self, got, expected,
+                                                      pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatchRunner_pass(TestBatchRunner *self, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatchRunner_VPass(self, pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatchRunner_fail(TestBatchRunner *self, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatchRunner_VFail(self, pattern, args);
+    va_end(args);
+    return result;
+}
+
+void
+TestBatchRunner_skip(TestBatchRunner *self, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    TestBatchRunner_VSkip(self, pattern, args);
+    va_end(args);
+}
+
+bool
+TestBatchRunner_vtest_true(TestBatchRunner *self, bool condition,
+                           const char *pattern, va_list args) {
+    return S_vtest_true(self, condition, pattern, args);
+}
+
+bool
+TestBatchRunner_vtest_false(TestBatchRunner *self, bool condition,
+                            const char *pattern, va_list args) {
+    return S_vtest_true(self, !condition, pattern, args);
+}
+
+bool
+TestBatchRunner_vtest_int_equals(TestBatchRunner *self, long got,
+                                 long expected, const char *pattern,
+                                 va_list args) {
+    bool pass = (got == expected);
+    S_vtest_true(self, pass, pattern, args);
+    if (!pass) {
+        TestFormatter_Test_Comment(self->formatter,
+                                   "Expected '%ld', got '%ld'.\n",
+                                   expected, got);
+    }
+    return pass;
+}
+
+bool
+TestBatchRunner_vtest_float_equals(TestBatchRunner *self, double got,
+                                   double expected, const char *pattern,
+                                   va_list args) {
+    double relative_error = got / expected - 1.0;
+    bool   pass           = (fabs(relative_error) < 1e-6);
+    S_vtest_true(self, pass, pattern, args);
+    if (!pass) {
+        TestFormatter_Test_Comment(self->formatter,
+                                   "Expected '%e', got '%e'.\n",
+                                   expected, got);
+    }
+    return pass;
+}
+
+bool
+TestBatchRunner_vtest_string_equals(TestBatchRunner *self, const char *got,
+                                    const char *expected, const char *pattern,
+                                    va_list args) {
+    bool pass = (strcmp(got, expected) == 0);
+    S_vtest_true(self, pass, pattern, args);
+    if (!pass) {
+        TestFormatter_Test_Comment(self->formatter,
+                                   "Expected '%s', got '%s'.\n",
+                                   expected, got);
+    }
+    return pass;
+}
+
+bool
+TestBatchRunner_vpass(TestBatchRunner *self, const char *pattern,
+                      va_list args) {
+    return S_vtest_true(self, true, pattern, args);
+}
+
+bool
+TestBatchRunner_vfail(TestBatchRunner *self, const char *pattern,
+                      va_list args) {
+    return S_vtest_true(self, false, pattern, args);
+}
+
+void
+TestBatchRunner_vskip(TestBatchRunner *self, const char *pattern,
+                      va_list args) {
+    self->test_num++;
+    // TODO: Add a VTest_Skip method to TestFormatter
+    TestFormatter_VTest_Result(self->formatter, true, self->test_num,
+                               pattern, args);
+    self->num_skipped++;
+}
+
+static bool
+S_vtest_true(TestBatchRunner* self, bool condition, const char *pattern,
+             va_list args) {
+    // Increment test number.
+    self->test_num++;
+
+    if (condition) {
+        self->num_passed++;
+    }
+    else {
+        self->num_failed++;
+    }
+
+    TestFormatter_VTest_Result(self->formatter, condition, self->test_num,
+                               pattern, args);
+
+    return condition;
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestBatchRunner.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestBatchRunner.cfh b/core/Clownfish/TestHarness/TestBatchRunner.cfh
new file mode 100644
index 0000000..ea993bb
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestBatchRunner.cfh
@@ -0,0 +1,135 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Clownfish;
+
+/** Run a single test batch and collect statistics.
+ */
+class Clownfish::TestHarness::TestBatchRunner inherits Clownfish::Obj {
+    TestFormatter *formatter;
+    uint32_t       test_num;
+    uint32_t       num_planned;
+    uint32_t       num_passed;
+    uint32_t       num_failed;
+    uint32_t       num_skipped;
+
+    inert incremented TestBatchRunner*
+    new(TestFormatter *formatter);
+
+    inert TestBatchRunner*
+    init(TestBatchRunner *self, TestFormatter *formatter);
+
+    public void
+    Destroy(TestBatchRunner *self);
+
+    /** Run the test batch and print test output and diagnosis.
+     *
+     * @return true if the test batch passed.
+     */
+    bool
+    Run_Batch(TestBatchRunner *self, TestBatch *batch);
+
+    void
+    Plan(TestBatchRunner *self, TestBatch *batch, uint32_t num_planned);
+
+    /** Return the number of tests planned.
+     */
+    uint32_t
+    Get_Num_Planned(TestBatchRunner *self);
+
+    /** Return the number of tests run.
+     */
+    uint32_t
+    Get_Num_Tests(TestBatchRunner *self);
+
+    /** Return the number of failed tests.
+     */
+    uint32_t
+    Get_Num_Failed(TestBatchRunner *self);
+
+    bool
+    Test_True(TestBatchRunner *self, bool condition, const char *pattern, ...);
+
+    bool
+    Test_False(TestBatchRunner *self, bool condition, const char *pattern,
+               ...);
+
+    bool
+    Test_Int_Equals(TestBatchRunner *self, long got, long expected,
+                    const char *pattern, ...);
+
+    bool
+    Test_Float_Equals(TestBatchRunner *self, double got, double expected,
+                      const char *pattern, ...);
+
+    bool
+    Test_String_Equals(TestBatchRunner *self, const char *got,
+                       const char *expected, const char *pattern, ...);
+
+    bool
+    Pass(TestBatchRunner *self, const char *pattern, ...);
+
+    bool
+    Fail(TestBatchRunner *self, const char *pattern, ...);
+
+    void
+    Skip(TestBatchRunner *self, const char *pattern, ...);
+
+    bool
+    VTest_True(TestBatchRunner *self, bool condition, const char *pattern,
+               va_list args);
+
+    bool
+    VTest_False(TestBatchRunner *self, bool condition, const char *pattern,
+                va_list args);
+
+    bool
+    VTest_Int_Equals(TestBatchRunner *self, long got, long expected,
+                     const char *pattern, va_list args);
+
+    bool
+    VTest_Float_Equals(TestBatchRunner *self, double got, double expected,
+                       const char *pattern, va_list args);
+
+    bool
+    VTest_String_Equals(TestBatchRunner *self, const char *got,
+                        const char *expected, const char *pattern,
+                        va_list args);
+
+    bool
+    VPass(TestBatchRunner *self, const char *pattern, va_list args);
+
+    bool
+    VFail(TestBatchRunner *self, const char *pattern, va_list args);
+
+    void
+    VSkip(TestBatchRunner *self, const char *pattern, va_list args);
+}
+
+__C__
+#ifdef CFISH_USE_SHORT_NAMES
+  #define TEST_TRUE            Cfish_TestBatchRunner_Test_True
+  #define TEST_FALSE           Cfish_TestBatchRunner_Test_False
+  #define TEST_INT_EQ          Cfish_TestBatchRunner_Test_Int_Equals
+  #define TEST_FLOAT_EQ        Cfish_TestBatchRunner_Test_Float_Equals
+  #define TEST_STR_EQ          Cfish_TestBatchRunner_Test_String_Equals
+  #define PASS                 Cfish_TestBatchRunner_Pass
+  #define FAIL                 Cfish_TestBatchRunner_Fail
+  #define SKIP                 Cfish_TestBatchRunner_Skip
+#endif
+__END_C__
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestFormatter.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestFormatter.c b/core/Clownfish/TestHarness/TestFormatter.c
index b6f0ac0..8f0d08a 100644
--- a/core/Clownfish/TestHarness/TestFormatter.c
+++ b/core/Clownfish/TestHarness/TestFormatter.c
@@ -22,10 +22,11 @@
 #define CHY_USE_SHORT_NAMES
 
 #include "Clownfish/TestHarness/TestFormatter.h"
+
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/TestHarness/TestBatch.h"
-#include "Clownfish/TestHarness/TestRunner.h"
+#include "Clownfish/TestHarness/TestSuiteRunner.h"
 #include "Clownfish/VTable.h"
 
 TestFormatter*
@@ -35,28 +36,27 @@ TestFormatter_init(TestFormatter *self) {
 }
 
 void
-TestFormatter_test_result(void *vself, bool pass, uint32_t test_num,
+TestFormatter_test_result(TestFormatter *self, bool pass, uint32_t test_num,
                           const char *fmt, ...) {
     va_list args;
     va_start(args, fmt);
-    TestFormatter_VTest_Result((TestFormatter*)vself, pass, test_num, fmt,
-                               args);
+    TestFormatter_VTest_Result(self, pass, test_num, fmt, args);
     va_end(args);
 }
 
 void
-TestFormatter_test_comment(void *vself, const char *fmt, ...) {
+TestFormatter_test_comment(TestFormatter *self, const char *fmt, ...) {
     va_list args;
     va_start(args, fmt);
-    TestFormatter_VTest_Comment((TestFormatter*)vself, fmt, args);
+    TestFormatter_VTest_Comment(self, fmt, args);
     va_end(args);
 }
 
 void
-TestFormatter_batch_comment(void *vself, const char *fmt, ...) {
+TestFormatter_batch_comment(TestFormatter *self, const char *fmt, ...) {
     va_list args;
     va_start(args, fmt);
-    TestFormatter_VBatch_Comment((TestFormatter*)vself, fmt, args);
+    TestFormatter_VBatch_Comment(self, fmt, args);
     va_end(args);
 }
 
@@ -73,7 +73,8 @@ TestFormatterCF_init(TestFormatterCF *self) {
 }
 
 void
-TestFormatterCF_batch_prologue(TestFormatterCF *self, TestBatch *batch) {
+TestFormatterCF_batch_prologue(TestFormatterCF *self, TestBatch *batch,
+                               uint32_t num_planned) {
     UNUSED_VAR(self);
     CharBuf *class_name = TestBatch_Get_Class_Name(batch);
     printf("Running %s...\n", CB_Get_Ptr8(class_name));
@@ -108,12 +109,13 @@ TestFormatterCF_vbatch_comment(TestFormatterCF *self, const char *fmt,
 }
 
 void
-TestFormatterCF_summary(TestFormatterCF *self, TestRunner *runner) {
+TestFormatterCF_summary(TestFormatterCF *self, TestSuiteRunner *runner) {
     UNUSED_VAR(self);
-    uint32_t num_batches        = TestRunner_Get_Num_Batches(runner);
-    uint32_t num_batches_failed = TestRunner_Get_Num_Batches_Failed(runner);
-    uint32_t num_tests          = TestRunner_Get_Num_Tests(runner);
-    uint32_t num_tests_failed   = TestRunner_Get_Num_Tests_Failed(runner);
+    uint32_t num_batches = TestSuiteRunner_Get_Num_Batches(runner);
+    uint32_t num_batches_failed
+        = TestSuiteRunner_Get_Num_Batches_Failed(runner);
+    uint32_t num_tests = TestSuiteRunner_Get_Num_Tests(runner);
+    uint32_t num_tests_failed = TestSuiteRunner_Get_Num_Tests_Failed(runner);
 
     if (num_batches == 0) {
         printf("No tests planned or run.\n");
@@ -143,9 +145,10 @@ TestFormatterTAP_init(TestFormatterTAP *self) {
 }
 
 void
-TestFormatterTAP_batch_prologue(TestFormatterTAP *self, TestBatch *batch) {
+TestFormatterTAP_batch_prologue(TestFormatterTAP *self, TestBatch *batch,
+                                uint32_t num_planned) {
     UNUSED_VAR(self);
-    printf("1..%u\n", TestBatch_Get_Num_Planned(batch));
+    printf("1..%u\n", num_planned);
 }
 
 void
@@ -176,7 +179,7 @@ TestFormatterTAP_vbatch_comment(TestFormatterTAP *self, const char *fmt,
 }
 
 void
-TestFormatterTAP_summary(TestFormatterTAP *self, TestRunner *runner) {
+TestFormatterTAP_summary(TestFormatterTAP *self, TestSuiteRunner *runner) {
     UNUSED_VAR(self);
     UNUSED_VAR(runner);
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestFormatter.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestFormatter.cfh b/core/Clownfish/TestHarness/TestFormatter.cfh
index 06402d2..d42c6fa 100644
--- a/core/Clownfish/TestHarness/TestFormatter.cfh
+++ b/core/Clownfish/TestHarness/TestFormatter.cfh
@@ -16,29 +16,29 @@
 
 parcel Clownfish;
 
-/**
- * Abstract base class for Clownfish test formatters.
+/** Abstract base class for Clownfish test formatters.
  */
 abstract class Clownfish::TestHarness::TestFormatter inherits Clownfish::Obj {
     inert TestFormatter*
     init(TestFormatter *self);
 
-    inert void
-    test_result(void *vself, bool pass, uint32_t test_num, const char *fmt,
-                ...);
+    void
+    Test_Result(TestFormatter *self, bool pass, uint32_t test_num,
+                const char *fmt, ...);
 
-    inert void
-    test_comment(void *vself, const char *fmt, ...);
+    void
+    Test_Comment(TestFormatter *self, const char *fmt, ...);
 
-    inert void
-    batch_comment(void *vself, const char *fmt, ...);
+    void
+    Batch_Comment(TestFormatter *self, const char *fmt, ...);
 
     /** Print output at the beginning of a test batch.
      *
      * @param batch The test batch.
      */
     abstract void
-    Batch_Prologue(TestFormatter *self, TestBatch *batch);
+    Batch_Prologue(TestFormatter *self, TestBatch *batch,
+                   uint32_t num_planned);
 
     /** Print the result of a single test.
      *
@@ -72,10 +72,11 @@ abstract class Clownfish::TestHarness::TestFormatter inherits Clownfish::Obj {
      * @param runner The test runner.
      */
     abstract void
-    Summary(TestFormatter *self, TestRunner *runner);
+    Summary(TestFormatter *self, TestSuiteRunner *runner);
 }
 
-/**
+/** TestFormatter for "Clownfish" format.
+ *
  * A TestFormatter that produces human-readable output in a custom
  * "Clownfish" format.
  */
@@ -89,7 +90,8 @@ class Clownfish::Test::Formatter::TestFormatterCF
     init(TestFormatterCF *self);
 
     void
-    Batch_Prologue(TestFormatterCF *self, TestBatch *batch);
+    Batch_Prologue(TestFormatterCF *self, TestBatch *batch,
+                   uint32_t num_planned);
 
     void
     VTest_Result(TestFormatterCF *self, bool pass, uint32_t test_num,
@@ -102,10 +104,11 @@ class Clownfish::Test::Formatter::TestFormatterCF
     VBatch_Comment(TestFormatterCF *self, const char *fmt, va_list args);
 
     void
-    Summary(TestFormatterCF *self, TestRunner *runner);
+    Summary(TestFormatterCF *self, TestSuiteRunner *runner);
 }
 
-/**
+/** TestFormatter for TAP output.
+ *
  * A TestFormatter that produces TAP output (Test Anything Protocol).
  * See http://testanything.org/
  */
@@ -119,7 +122,8 @@ class Clownfish::Test::Formatter::TestFormatterTAP
     init(TestFormatterTAP *self);
 
     void
-    Batch_Prologue(TestFormatterTAP *self, TestBatch *batch);
+    Batch_Prologue(TestFormatterTAP *self, TestBatch *batch,
+                   uint32_t num_planned);
 
     void
     VTest_Result(TestFormatterTAP *self, bool pass, uint32_t test_num,
@@ -132,7 +136,7 @@ class Clownfish::Test::Formatter::TestFormatterTAP
     VBatch_Comment(TestFormatterTAP *self, const char *fmt, va_list args);
 
     void
-    Summary(TestFormatterTAP *self, TestRunner *runner);
+    Summary(TestFormatterTAP *self, TestSuiteRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/TestHarness/TestRunner.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestRunner.c b/core/Clownfish/TestHarness/TestRunner.c
deleted file mode 100644
index 3132d39..0000000
--- a/core/Clownfish/TestHarness/TestRunner.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_CFISH_TESTRUNNER
-#define CFISH_USE_SHORT_NAMES
-#define LUCY_USE_SHORT_NAMES
-#define CHY_USE_SHORT_NAMES
-
-#include "Clownfish/TestHarness/TestRunner.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/TestHarness/TestBatch.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
-#include "Clownfish/VTable.h"
-
-TestRunner*
-TestRunner_new(TestFormatter *formatter) {
-    TestRunner *self = (TestRunner*)VTable_Make_Obj(TESTRUNNER);
-    return TestRunner_init(self, formatter);
-}
-
-TestRunner*
-TestRunner_init(TestRunner *self, TestFormatter *formatter) {
-    self->formatter          = (TestFormatter*)INCREF(formatter);
-    self->num_tests          = 0;
-    self->num_tests_failed   = 0;
-    self->num_batches        = 0;
-    self->num_batches_failed = 0;
-
-    return self;
-}
-
-void
-TestRunner_destroy(TestRunner *self) {
-    DECREF(self->formatter);
-    SUPER_DESTROY(self, TESTRUNNER);
-}
-
-bool
-TestRunner_run_batch(TestRunner *self, TestBatch *batch) {
-    bool success = TestBatch_Run(batch);
-
-    self->num_tests        += TestBatch_Get_Num_Tests(batch);
-    self->num_tests_failed += TestBatch_Get_Num_Failed(batch);
-    self->num_batches      += 1;
-
-    if (!success) {
-        self->num_batches_failed += 1;
-    }
-
-    return success;
-}
-
-bool
-TestRunner_finish(TestRunner *self) {
-    TestFormatter_Summary(self->formatter, self);
-
-    return self->num_batches != 0 && self->num_batches_failed == 0;
-}
-
-uint32_t
-TestRunner_get_num_tests(TestRunner *self) {
-    return self->num_tests;
-}
-
-uint32_t
-TestRunner_get_num_tests_failed(TestRunner *self) {
-    return self->num_tests_failed;
-}
-
-uint32_t
-TestRunner_get_num_batches(TestRunner *self) {
-    return self->num_batches;
-}
-
-uint32_t
-TestRunner_get_num_batches_failed(TestRunner *self) {
-    return self->num_batches_failed;
-}
-
-


[lucy-commits] [08/26] Move Clownfish runtime tests to a separate parcel

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestVArray.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestVArray.c b/core/Clownfish/Test/TestVArray.c
new file mode 100644
index 0000000..99b5918
--- /dev/null
+++ b/core/Clownfish/Test/TestVArray.c
@@ -0,0 +1,353 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestVArray.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Num.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/VArray.h"
+#include "Clownfish/VTable.h"
+
+TestVArray*
+TestVArray_new(TestFormatter *formatter) {
+    TestVArray *self = (TestVArray*)VTable_Make_Obj(TESTVARRAY);
+    return TestVArray_init(self, formatter);
+}
+
+TestVArray*
+TestVArray_init(TestVArray *self, TestFormatter *formatter) {
+    return (TestVArray*)TestBatch_init((TestBatch*)self, 45, formatter);
+}
+
+static CharBuf*
+S_new_cb(const char *text) {
+    return CB_new_from_utf8(text, strlen(text));
+}
+
+static void
+test_Equals(TestBatch *batch) {
+    VArray *array = VA_new(0);
+    VArray *other = VA_new(0);
+    ZombieCharBuf *stuff = ZCB_WRAP_STR("stuff", 5);
+
+    TEST_TRUE(batch, VA_Equals(array, (Obj*)other),
+              "Empty arrays are equal");
+
+    VA_Push(array, (Obj*)CFISH_TRUE);
+    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
+               "Add one elem and Equals returns false");
+
+    VA_Push(other, (Obj*)CFISH_TRUE);
+    TEST_TRUE(batch, VA_Equals(array, (Obj*)other),
+              "Add a matching elem and Equals returns true");
+
+    VA_Store(array, 2, (Obj*)CFISH_TRUE);
+    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
+               "Add elem after a NULL and Equals returns false");
+
+    VA_Store(other, 2, (Obj*)CFISH_TRUE);
+    TEST_TRUE(batch, VA_Equals(array, (Obj*)other),
+              "Empty elems don't spoil Equals");
+
+    VA_Store(other, 2, INCREF(stuff));
+    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
+               "Non-matching value spoils Equals");
+
+    VA_Excise(array, 1, 2); // removes empty elems
+    VA_Delete(other, 1);    // leaves NULL in place of deleted elem
+    VA_Delete(other, 2);
+    TEST_FALSE(batch, VA_Equals(array, (Obj*)other),
+               "Empty trailing elements spoil Equals");
+
+    DECREF(array);
+    DECREF(other);
+}
+
+static void
+test_Store_Fetch(TestBatch *batch) {
+    VArray *array = VA_new(0);
+    CharBuf *elem;
+
+    TEST_TRUE(batch, VA_Fetch(array, 2) == NULL, "Fetch beyond end");
+
+    VA_Store(array, 2, (Obj*)CB_newf("foo"));
+    elem = (CharBuf*)CERTIFY(VA_Fetch(array, 2), CHARBUF);
+    TEST_INT_EQ(batch, 3, VA_Get_Size(array), "Store updates size");
+    TEST_TRUE(batch, CB_Equals_Str(elem, "foo", 3), "Store");
+
+    INCREF(elem);
+    TEST_INT_EQ(batch, 2, CB_Get_RefCount(elem),
+                "start with refcount of 2");
+    VA_Store(array, 2, (Obj*)CB_newf("bar"));
+    TEST_INT_EQ(batch, 1, CB_Get_RefCount(elem),
+                "Displacing elem via Store updates refcount");
+    DECREF(elem);
+    elem = (CharBuf*)CERTIFY(VA_Fetch(array, 2), CHARBUF);
+    TEST_TRUE(batch, CB_Equals_Str(elem, "bar", 3), "Store displacement");
+
+    DECREF(array);
+}
+
+static void
+test_Push_Pop_Shift_Unshift(TestBatch *batch) {
+    VArray *array = VA_new(0);
+    CharBuf *elem;
+
+    TEST_INT_EQ(batch, VA_Get_Size(array), 0, "size starts at 0");
+    VA_Push(array, (Obj*)CB_newf("a"));
+    VA_Push(array, (Obj*)CB_newf("b"));
+    VA_Push(array, (Obj*)CB_newf("c"));
+
+    TEST_INT_EQ(batch, VA_Get_Size(array), 3, "size after Push");
+    TEST_TRUE(batch, NULL != CERTIFY(VA_Fetch(array, 2), CHARBUF), "Push");
+
+    elem = (CharBuf*)CERTIFY(VA_Shift(array), CHARBUF);
+    TEST_TRUE(batch, CB_Equals_Str(elem, "a", 1), "Shift");
+    TEST_INT_EQ(batch, VA_Get_Size(array), 2, "size after Shift");
+    DECREF(elem);
+
+    elem = (CharBuf*)CERTIFY(VA_Pop(array), CHARBUF);
+    TEST_TRUE(batch, CB_Equals_Str(elem, "c", 1), "Pop");
+    TEST_INT_EQ(batch, VA_Get_Size(array), 1, "size after Pop");
+    DECREF(elem);
+
+    VA_Unshift(array, (Obj*)CB_newf("foo"));
+    elem = (CharBuf*)CERTIFY(VA_Fetch(array, 0), CHARBUF);
+    TEST_TRUE(batch, CB_Equals_Str(elem, "foo", 3), "Unshift");
+    TEST_INT_EQ(batch, VA_Get_Size(array), 2, "size after Shift");
+
+    DECREF(array);
+}
+
+static void
+test_Delete(TestBatch *batch) {
+    VArray *wanted = VA_new(5);
+    VArray *got    = VA_new(5);
+    uint32_t i;
+
+    for (i = 0; i < 5; i++) { VA_Push(got, (Obj*)CB_newf("%u32", i)); }
+    VA_Store(wanted, 0, (Obj*)CB_newf("0", i));
+    VA_Store(wanted, 1, (Obj*)CB_newf("1", i));
+    VA_Store(wanted, 4, (Obj*)CB_newf("4", i));
+    DECREF(VA_Delete(got, 2));
+    DECREF(VA_Delete(got, 3));
+    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got), "Delete");
+
+    DECREF(wanted);
+    DECREF(got);
+}
+
+static void
+test_Resize(TestBatch *batch) {
+    VArray *array = VA_new(3);
+    uint32_t i;
+
+    for (i = 0; i < 2; i++) { VA_Push(array, (Obj*)CB_newf("%u32", i)); }
+    TEST_INT_EQ(batch, VA_Get_Capacity(array), 3, "Start with capacity 3");
+
+    VA_Resize(array, 4);
+    TEST_INT_EQ(batch, VA_Get_Size(array), 4, "Resize up");
+    TEST_INT_EQ(batch, VA_Get_Capacity(array), 4,
+                "Resize changes capacity");
+
+    VA_Resize(array, 2);
+    TEST_INT_EQ(batch, VA_Get_Size(array), 2, "Resize down");
+    TEST_TRUE(batch, VA_Fetch(array, 2) == NULL, "Resize down zaps elem");
+
+    DECREF(array);
+}
+
+static void
+test_Excise(TestBatch *batch) {
+    VArray *wanted = VA_new(5);
+    VArray *got    = VA_new(5);
+
+    for (uint32_t i = 0; i < 5; i++) {
+        VA_Push(wanted, (Obj*)CB_newf("%u32", i));
+        VA_Push(got, (Obj*)CB_newf("%u32", i));
+    }
+
+    VA_Excise(got, 7, 1);
+    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
+              "Excise outside of range is no-op");
+
+    VA_Excise(got, 2, 2);
+    DECREF(VA_Delete(wanted, 2));
+    DECREF(VA_Delete(wanted, 3));
+    VA_Store(wanted, 2, VA_Delete(wanted, 4));
+    VA_Resize(wanted, 3);
+    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
+              "Excise multiple elems");
+
+    VA_Excise(got, 2, 2);
+    VA_Resize(wanted, 2);
+    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
+              "Splicing too many elems truncates");
+
+    VA_Excise(got, 0, 1);
+    VA_Store(wanted, 0, VA_Delete(wanted, 1));
+    VA_Resize(wanted, 1);
+    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got),
+              "Excise first elem");
+
+    DECREF(got);
+    DECREF(wanted);
+}
+
+static void
+test_Push_VArray(TestBatch *batch) {
+    VArray *wanted  = VA_new(0);
+    VArray *got     = VA_new(0);
+    VArray *scratch = VA_new(0);
+    uint32_t i;
+
+    for (i = 0; i < 4; i++) { VA_Push(wanted, (Obj*)CB_newf("%u32", i)); }
+    for (i = 0; i < 2; i++) { VA_Push(got, (Obj*)CB_newf("%u32", i)); }
+    for (i = 2; i < 4; i++) { VA_Push(scratch, (Obj*)CB_newf("%u32", i)); }
+
+    VA_Push_VArray(got, scratch);
+    TEST_TRUE(batch, VA_Equals(wanted, (Obj*)got), "Push_VArray");
+
+    DECREF(wanted);
+    DECREF(got);
+    DECREF(scratch);
+}
+
+static void
+test_Slice(TestBatch *batch) {
+    VArray *array = VA_new(0);
+    for (uint32_t i = 0; i < 10; i++) { VA_Push(array, (Obj*)CB_newf("%u32", i)); }
+    {
+        VArray *slice = VA_Slice(array, 0, 10);
+        TEST_TRUE(batch, VA_Equals(array, (Obj*)slice), "Slice entire array");
+        DECREF(slice);
+    }
+    {
+        VArray *slice = VA_Slice(array, 0, 11);
+        TEST_TRUE(batch, VA_Equals(array, (Obj*)slice),
+            "Exceed length");
+        DECREF(slice);
+    }
+    {
+        VArray *wanted = VA_new(0);
+        VA_Push(wanted, (Obj*)CB_newf("9"));
+        VArray *slice = VA_Slice(array, 9, 11);
+        TEST_TRUE(batch, VA_Equals(slice, (Obj*)wanted),
+            "Exceed length, start near end");
+        DECREF(slice);
+        DECREF(wanted);
+    }
+    {
+        VArray *slice = VA_Slice(array, 0, 0);
+        TEST_TRUE(batch, VA_Get_Size(slice) == 0, "empty slice");
+        DECREF(slice);
+    }
+    {
+        VArray *slice = VA_Slice(array, 20, 1);
+        TEST_TRUE(batch, VA_Get_Size(slice) ==  0, "exceed offset");
+        DECREF(slice);
+    }
+    {
+        VArray *wanted = VA_new(0);
+        VA_Push(wanted, (Obj*)CB_newf("9"));
+        VArray *slice = VA_Slice(array, 9, UINT32_MAX - 1);
+        TEST_TRUE(batch, VA_Get_Size(slice) == 1, "guard against overflow");
+        DECREF(slice);
+        DECREF(wanted);
+    }
+    DECREF(array);
+}
+
+static void
+test_Clone_and_Shallow_Copy(TestBatch *batch) {
+    VArray *array = VA_new(0);
+    VArray *twin;
+    uint32_t i;
+
+    for (i = 0; i < 10; i++) {
+        VA_Push(array, (Obj*)CB_newf("%u32", i));
+    }
+    twin = VA_Shallow_Copy(array);
+    TEST_TRUE(batch, VA_Equals(array, (Obj*)twin), "Shallow_Copy");
+    TEST_TRUE(batch, VA_Fetch(array, 1) == VA_Fetch(twin, 1),
+              "Shallow_Copy doesn't clone elements");
+    DECREF(twin);
+
+    twin = VA_Clone(array);
+    TEST_TRUE(batch, VA_Equals(array, (Obj*)twin), "Clone");
+    TEST_TRUE(batch, VA_Fetch(array, 1) != VA_Fetch(twin, 1),
+              "Clone performs deep clone");
+
+    DECREF(array);
+    DECREF(twin);
+}
+
+static void
+test_Dump_and_Load(TestBatch *batch) {
+    VArray *array = VA_new(0);
+    Obj    *dump;
+    VArray *loaded;
+
+    VA_Push(array, (Obj*)S_new_cb("foo"));
+    dump = (Obj*)VA_Dump(array);
+    loaded = (VArray*)Obj_Load(dump, dump);
+    TEST_TRUE(batch, VA_Equals(array, (Obj*)loaded),
+              "Dump => Load round trip");
+
+    DECREF(array);
+    DECREF(dump);
+    DECREF(loaded);
+}
+
+static void
+test_serialization(TestBatch *batch) {
+    VArray *array = VA_new(0);
+    VArray *dupe;
+    VA_Store(array, 1, (Obj*)CB_newf("foo"));
+    VA_Store(array, 3, (Obj*)CB_newf("bar"));
+    dupe = (VArray*)TestUtils_freeze_thaw((Obj*)array);
+    TEST_TRUE(batch, dupe && VA_Equals(array, (Obj*)dupe),
+              "Round trip through FREEZE/THAW");
+    DECREF(dupe);
+    DECREF(array);
+}
+
+void
+TestVArray_run_tests(TestVArray *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_Equals(batch);
+    test_Store_Fetch(batch);
+    test_Push_Pop_Shift_Unshift(batch);
+    test_Delete(batch);
+    test_Resize(batch);
+    test_Excise(batch);
+    test_Push_VArray(batch);
+    test_Slice(batch);
+    test_Clone_and_Shallow_Copy(batch);
+    test_Dump_and_Load(batch);
+    test_serialization(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/TestVArray.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestVArray.cfh b/core/Clownfish/Test/TestVArray.cfh
new file mode 100644
index 0000000..481dbb4
--- /dev/null
+++ b/core/Clownfish/Test/TestVArray.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::TestVArray
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestVArray*
+    new(TestFormatter *formatter);
+
+    inert TestVArray*
+    init(TestVArray *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestVArray *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/Util/TestAtomic.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestAtomic.c b/core/Clownfish/Test/Util/TestAtomic.c
new file mode 100644
index 0000000..3610f7d
--- /dev/null
+++ b/core/Clownfish/Test/Util/TestAtomic.c
@@ -0,0 +1,71 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/Util/TestAtomic.h"
+
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Util/Atomic.h"
+#include "Clownfish/VTable.h"
+
+TestAtomic*
+TestAtomic_new(TestFormatter *formatter) {
+    TestAtomic *self = (TestAtomic*)VTable_Make_Obj(TESTATOMIC);
+    return TestAtomic_init(self, formatter);
+}
+
+TestAtomic*
+TestAtomic_init(TestAtomic *self, TestFormatter *formatter) {
+    return (TestAtomic*)TestBatch_init((TestBatch*)self, 6, formatter);
+}
+
+static void
+test_cas_ptr(TestBatch *batch) {
+    int    foo = 1;
+    int    bar = 2;
+    int   *foo_pointer = &foo;
+    int   *bar_pointer = &bar;
+    int   *target      = NULL;
+
+    TEST_TRUE(batch,
+              Atomic_cas_ptr((void**)&target, NULL, foo_pointer),
+              "cas_ptr returns true on success");
+    TEST_TRUE(batch, target == foo_pointer, "cas_ptr sets target");
+
+    target = NULL;
+    TEST_FALSE(batch,
+               Atomic_cas_ptr((void**)&target, bar_pointer, foo_pointer),
+               "cas_ptr returns false when it old_value doesn't match");
+    TEST_TRUE(batch, target == NULL,
+              "cas_ptr doesn't do anything to target when old_value doesn't match");
+
+    target = foo_pointer;
+    TEST_TRUE(batch,
+              Atomic_cas_ptr((void**)&target, foo_pointer, bar_pointer),
+              "cas_ptr from one value to another");
+    TEST_TRUE(batch, target == bar_pointer, "cas_ptr sets target");
+}
+
+void
+TestAtomic_run_tests(TestAtomic *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_cas_ptr(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/Util/TestAtomic.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestAtomic.cfh b/core/Clownfish/Test/Util/TestAtomic.cfh
new file mode 100644
index 0000000..90d905e
--- /dev/null
+++ b/core/Clownfish/Test/Util/TestAtomic.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::Util::TestAtomic
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestAtomic*
+    new(TestFormatter *formatter);
+
+    inert TestAtomic*
+    init(TestAtomic *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestAtomic *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/Util/TestMemory.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestMemory.c b/core/Clownfish/Test/Util/TestMemory.c
new file mode 100644
index 0000000..a3ac538
--- /dev/null
+++ b/core/Clownfish/Test/Util/TestMemory.c
@@ -0,0 +1,124 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CHY_USE_SHORT_NAMES
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/Util/TestMemory.h"
+
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Util/Memory.h"
+#include "Clownfish/VTable.h"
+
+TestMemory*
+TestMemory_new(TestFormatter *formatter) {
+    TestMemory *self = (TestMemory*)VTable_Make_Obj(TESTMEMORY);
+    return TestMemory_init(self, formatter);
+}
+
+TestMemory*
+TestMemory_init(TestMemory *self, TestFormatter *formatter) {
+    return (TestMemory*)TestBatch_init((TestBatch*)self, 30, formatter);
+}
+
+static void
+test_oversize__growth_rate(TestBatch *batch) {
+    bool     success             = true;
+    uint64_t size                = 0;
+    double   growth_count        = 0;
+    double   average_growth_rate = 0.0;
+
+    while (size < SIZE_MAX) {
+        uint64_t next_size = Memory_oversize((size_t)size + 1, sizeof(void*));
+        if (next_size < size) {
+            success = false;
+            FAIL(batch, "Asked for %" PRId64 ", got smaller amount %" PRId64,
+                 size + 1, next_size);
+            break;
+        }
+        if (size > 0) {
+            growth_count += 1;
+            double growth_rate = U64_TO_DOUBLE(next_size) /
+                                 U64_TO_DOUBLE(size);
+            double sum = growth_rate + (growth_count - 1) * average_growth_rate;
+            average_growth_rate = sum / growth_count;
+            if (average_growth_rate < 1.1) {
+                FAIL(batch, "Average growth rate dropped below 1.1x: %f",
+                     average_growth_rate);
+                success = false;
+                break;
+            }
+        }
+        size = next_size;
+    }
+    TEST_TRUE(batch, growth_count > 0, "Grew %f times", growth_count);
+    if (success) {
+        TEST_TRUE(batch, average_growth_rate > 1.1,
+                  "Growth rate of oversize() averages above 1.1: %.3f",
+                  average_growth_rate);
+    }
+
+    for (int minimum = 1; minimum < 8; minimum++) {
+        uint64_t next_size = Memory_oversize(minimum, sizeof(void*));
+        double growth_rate = U64_TO_DOUBLE(next_size) / (double)minimum;
+        TEST_TRUE(batch, growth_rate > 1.2,
+                  "Growth rate is higher for smaller arrays (%d, %.3f)", minimum,
+                  growth_rate);
+    }
+}
+
+static void
+test_oversize__ceiling(TestBatch *batch) {
+    for (int width = 0; width < 10; width++) {
+        size_t size = Memory_oversize(SIZE_MAX, width);
+        TEST_TRUE(batch, size == SIZE_MAX,
+                  "Memory_oversize hits ceiling at SIZE_MAX (width %d)", width);
+        size = Memory_oversize(SIZE_MAX - 1, width);
+        TEST_TRUE(batch, size == SIZE_MAX,
+                  "Memory_oversize hits ceiling at SIZE_MAX (width %d)", width);
+    }
+}
+
+static void
+test_oversize__rounding(TestBatch *batch) {
+    int widths[] = { 1, 2, 4, 0 };
+
+    for (int width_tick = 0; widths[width_tick] != 0; width_tick++) {
+        int width = widths[width_tick];
+        for (int i = 0; i < 25; i++) {
+            size_t size = Memory_oversize(i, width);
+            size_t bytes = size * width;
+            if (bytes % sizeof(void*) != 0) {
+                FAIL(batch, "Rounding failure for %d, width %d",
+                     i, width);
+                return;
+            }
+        }
+    }
+    PASS(batch, "Round allocations up to the size of a pointer");
+}
+
+void
+TestMemory_run_tests(TestMemory *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_oversize__growth_rate(batch);
+    test_oversize__ceiling(batch);
+    test_oversize__rounding(batch);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/Util/TestMemory.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestMemory.cfh b/core/Clownfish/Test/Util/TestMemory.cfh
new file mode 100644
index 0000000..23252c2
--- /dev/null
+++ b/core/Clownfish/Test/Util/TestMemory.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::Util::TestMemory
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestMemory*
+    new(TestFormatter *formatter);
+
+    inert TestMemory*
+    init(TestMemory *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestMemory *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/Util/TestNumberUtils.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestNumberUtils.c b/core/Clownfish/Test/Util/TestNumberUtils.c
new file mode 100644
index 0000000..b524818
--- /dev/null
+++ b/core/Clownfish/Test/Util/TestNumberUtils.c
@@ -0,0 +1,381 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/Util/TestNumberUtils.h"
+
+#include "Clownfish/Err.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/Util/Memory.h"
+#include "Clownfish/Util/NumberUtils.h"
+#include "Clownfish/VTable.h"
+
+TestNumberUtils*
+TestNumUtil_new(TestFormatter *formatter) {
+    TestNumberUtils *self = (TestNumberUtils*)VTable_Make_Obj(TESTNUMBERUTILS);
+    return TestNumUtil_init(self, formatter);
+}
+
+TestNumberUtils*
+TestNumUtil_init(TestNumberUtils *self, TestFormatter *formatter) {
+    return (TestNumberUtils*)TestBatch_init((TestBatch*)self, 1196, formatter);
+}
+
+static void
+test_u1(TestBatch *batch) {
+    size_t    count   = 64;
+    uint64_t *ints    = TestUtils_random_u64s(NULL, count, 0, 2);
+    size_t    amount  = count / 8;
+    uint8_t  *bits    = (uint8_t*)CALLOCATE(amount, sizeof(uint8_t));
+
+    for (size_t i = 0; i < count; i++) {
+        if (ints[i]) { NumUtil_u1set(bits, i); }
+    }
+    for (size_t i = 0; i < count; i++) {
+        TEST_INT_EQ(batch, NumUtil_u1get(bits, i), (long)ints[i],
+                    "u1 set/get");
+    }
+
+    for (size_t i = 0; i < count; i++) {
+        NumUtil_u1flip(bits, i);
+    }
+    for (size_t i = 0; i < count; i++) {
+        TEST_INT_EQ(batch, NumUtil_u1get(bits, i), !ints[i], "u1 flip");
+    }
+
+    FREEMEM(bits);
+    FREEMEM(ints);
+}
+
+static void
+test_u2(TestBatch *batch) {
+    size_t    count = 32;
+    uint64_t *ints = TestUtils_random_u64s(NULL, count, 0, 4);
+    uint8_t  *bits = (uint8_t*)CALLOCATE((count / 4), sizeof(uint8_t));
+
+    for (size_t i = 0; i < count; i++) {
+        NumUtil_u2set(bits, i, (uint8_t)ints[i]);
+    }
+    for (size_t i = 0; i < count; i++) {
+        TEST_INT_EQ(batch, NumUtil_u2get(bits, i), (long)ints[i], "u2");
+    }
+
+    FREEMEM(bits);
+    FREEMEM(ints);
+}
+
+static void
+test_u4(TestBatch *batch) {
+    size_t    count = 128;
+    uint64_t *ints  = TestUtils_random_u64s(NULL, count, 0, 16);
+    uint8_t  *bits  = (uint8_t*)CALLOCATE((count / 2), sizeof(uint8_t));
+
+    for (size_t i = 0; i < count; i++) {
+        NumUtil_u4set(bits, i, (uint8_t)ints[i]);
+    }
+    for (size_t i = 0; i < count; i++) {
+        TEST_INT_EQ(batch, NumUtil_u4get(bits, i), (long)ints[i], "u4");
+    }
+
+    FREEMEM(bits);
+    FREEMEM(ints);
+}
+
+static void
+test_c32(TestBatch *batch) {
+    uint64_t  mins[]   = { 0,   0x4000 - 100, (uint32_t)INT32_MAX - 100, UINT32_MAX - 10 };
+    uint64_t  limits[] = { 500, 0x4000 + 100, (uint32_t)INT32_MAX + 100, UINT32_MAX      };
+    uint32_t  set_num;
+    uint32_t  num_sets  = sizeof(mins) / sizeof(uint64_t);
+    size_t    count     = 64;
+    uint64_t *ints      = NULL;
+    size_t    amount    = count * C32_MAX_BYTES;
+    char     *encoded   = (char*)CALLOCATE(amount, sizeof(char));
+    char     *target    = encoded;
+    char     *limit     = target + amount;
+
+    for (set_num = 0; set_num < num_sets; set_num++) {
+        char *skip;
+        ints = TestUtils_random_u64s(ints, count,
+                                     mins[set_num], limits[set_num]);
+        target = encoded;
+        for (size_t i = 0; i < count; i++) {
+            NumUtil_encode_c32((uint32_t)ints[i], &target);
+        }
+        target = encoded;
+        skip   = encoded;
+        for (size_t i = 0; i < count; i++) {
+            TEST_INT_EQ(batch, NumUtil_decode_c32(&target), (long)ints[i],
+                        "c32 %lu", (long)ints[i]);
+            NumUtil_skip_cint(&skip);
+            if (target > limit) { THROW(ERR, "overrun"); }
+        }
+        TEST_TRUE(batch, skip == target, "skip %lu == %lu",
+                  (unsigned long)skip, (unsigned long)target);
+
+        target = encoded;
+        for (size_t i = 0; i < count; i++) {
+            NumUtil_encode_padded_c32((uint32_t)ints[i], &target);
+        }
+        TEST_TRUE(batch, target == limit,
+                  "padded c32 uses 5 bytes (%lu == %lu)", (unsigned long)target,
+                  (unsigned long)limit);
+        target = encoded;
+        skip   = encoded;
+        for (size_t i = 0; i < count; i++) {
+            TEST_INT_EQ(batch, NumUtil_decode_c32(&target), (long)ints[i],
+                        "padded c32 %lu", (long)ints[i]);
+            NumUtil_skip_cint(&skip);
+            if (target > limit) { THROW(ERR, "overrun"); }
+        }
+        TEST_TRUE(batch, skip == target, "skip padded %lu == %lu",
+                  (unsigned long)skip, (unsigned long)target);
+    }
+
+    target = encoded;
+    NumUtil_encode_c32(UINT32_MAX, &target);
+    target = encoded;
+    TEST_INT_EQ(batch, NumUtil_decode_c32(&target), UINT32_MAX, "c32 UINT32_MAX");
+
+    FREEMEM(encoded);
+    FREEMEM(ints);
+}
+
+static void
+test_c64(TestBatch *batch) {
+    uint64_t  mins[]    = { 0,   0x4000 - 100, (uint64_t)UINT32_MAX - 100,  UINT64_MAX - 10 };
+    uint64_t  limits[]  = { 500, 0x4000 + 100, (uint64_t)UINT32_MAX + 1000, UINT64_MAX      };
+    uint32_t  set_num;
+    uint32_t  num_sets  = sizeof(mins) / sizeof(uint64_t);
+    size_t    count     = 64;
+    uint64_t *ints      = NULL;
+    size_t    amount    = count * C64_MAX_BYTES;
+    char     *encoded   = (char*)CALLOCATE(amount, sizeof(char));
+    char     *target    = encoded;
+    char     *limit     = target + amount;
+
+    for (set_num = 0; set_num < num_sets; set_num++) {
+        char *skip;
+        ints = TestUtils_random_u64s(ints, count,
+                                     mins[set_num], limits[set_num]);
+        target = encoded;
+        for (size_t i = 0; i < count; i++) {
+            NumUtil_encode_c64(ints[i], &target);
+        }
+        target = encoded;
+        skip   = encoded;
+        for (size_t i = 0; i < count; i++) {
+            uint64_t got = NumUtil_decode_c64(&target);
+            TEST_TRUE(batch, got == ints[i],
+                      "c64 %" PRIu64 " == %" PRIu64, got, ints[i]);
+            if (target > limit) { THROW(ERR, "overrun"); }
+            NumUtil_skip_cint(&skip);
+        }
+        TEST_TRUE(batch, skip == target, "skip %lu == %lu",
+                  (unsigned long)skip, (unsigned long)target);
+    }
+
+    target = encoded;
+    NumUtil_encode_c64(UINT64_MAX, &target);
+    target = encoded;
+
+    uint64_t got = NumUtil_decode_c64(&target);
+    TEST_TRUE(batch, got == UINT64_MAX, "c64 UINT64_MAX");
+
+    FREEMEM(encoded);
+    FREEMEM(ints);
+}
+
+static void
+test_bigend_u16(TestBatch *batch) {
+    size_t    count     = 32;
+    uint64_t *ints      = TestUtils_random_u64s(NULL, count, 0, UINT16_MAX + 1);
+    size_t    amount    = (count + 1) * sizeof(uint16_t);
+    char     *allocated = (char*)CALLOCATE(amount, sizeof(char));
+    char     *encoded   = allocated + 1; // Intentionally misaligned.
+    char     *target    = encoded;
+
+    for (size_t i = 0; i < count; i++) {
+        NumUtil_encode_bigend_u16((uint16_t)ints[i], &target);
+        target += sizeof(uint16_t);
+    }
+    target = encoded;
+    for (size_t i = 0; i < count; i++) {
+        uint16_t got = NumUtil_decode_bigend_u16(target);
+        TEST_INT_EQ(batch, got, (long)ints[i], "bigend u16");
+        target += sizeof(uint16_t);
+    }
+
+    target = encoded;
+    NumUtil_encode_bigend_u16(1, &target);
+    TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian u16");
+    TEST_INT_EQ(batch, encoded[1], 1, "Truly big-endian u16");
+
+    FREEMEM(allocated);
+    FREEMEM(ints);
+}
+
+static void
+test_bigend_u32(TestBatch *batch) {
+    size_t    count     = 32;
+    uint64_t *ints      = TestUtils_random_u64s(NULL, count, 0, UINT64_C(1) + UINT32_MAX);
+    size_t    amount    = (count + 1) * sizeof(uint32_t);
+    char     *allocated = (char*)CALLOCATE(amount, sizeof(char));
+    char     *encoded   = allocated + 1; // Intentionally misaligned.
+    char     *target    = encoded;
+
+    for (size_t i = 0; i < count; i++) {
+        NumUtil_encode_bigend_u32((uint32_t)ints[i], &target);
+        target += sizeof(uint32_t);
+    }
+    target = encoded;
+    for (size_t i = 0; i < count; i++) {
+        uint32_t got = NumUtil_decode_bigend_u32(target);
+        TEST_INT_EQ(batch, got, (long)ints[i], "bigend u32");
+        target += sizeof(uint32_t);
+    }
+
+    target = encoded;
+    NumUtil_encode_bigend_u32(1, &target);
+    TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian u32");
+    TEST_INT_EQ(batch, encoded[3], 1, "Truly big-endian u32");
+
+    FREEMEM(allocated);
+    FREEMEM(ints);
+}
+
+static void
+test_bigend_u64(TestBatch *batch) {
+    size_t    count     = 32;
+    uint64_t *ints      = TestUtils_random_u64s(NULL, count, 0, UINT64_MAX);
+    size_t    amount    = (count + 1) * sizeof(uint64_t);
+    char     *allocated = (char*)CALLOCATE(amount, sizeof(char));
+    char     *encoded   = allocated + 1; // Intentionally misaligned.
+    char     *target    = encoded;
+
+    for (size_t i = 0; i < count; i++) {
+        NumUtil_encode_bigend_u64(ints[i], &target);
+        target += sizeof(uint64_t);
+    }
+    target = encoded;
+    for (size_t i = 0; i < count; i++) {
+        uint64_t got = NumUtil_decode_bigend_u64(target);
+        TEST_TRUE(batch, got == ints[i], "bigend u64");
+        target += sizeof(uint64_t);
+    }
+
+    target = encoded;
+    NumUtil_encode_bigend_u64(1, &target);
+    TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian");
+    TEST_INT_EQ(batch, encoded[7], 1, "Truly big-endian");
+
+    FREEMEM(allocated);
+    FREEMEM(ints);
+}
+
+static void
+test_bigend_f32(TestBatch *batch) {
+    float    source[]  = { -1.3f, 0.0f, 100.2f };
+    size_t   count     = 3;
+    size_t   amount    = (count + 1) * sizeof(float);
+    uint8_t *allocated = (uint8_t*)CALLOCATE(amount, sizeof(uint8_t));
+    uint8_t *encoded   = allocated + 1; // Intentionally misaligned.
+    uint8_t *target    = encoded;
+
+    for (size_t i = 0; i < count; i++) {
+        NumUtil_encode_bigend_f32(source[i], &target);
+        target += sizeof(float);
+    }
+    target = encoded;
+    for (size_t i = 0; i < count; i++) {
+        float got = NumUtil_decode_bigend_f32(target);
+        TEST_TRUE(batch, got == source[i], "bigend f32");
+        target += sizeof(float);
+    }
+
+    target = encoded;
+    NumUtil_encode_bigend_f32(-2.0f, &target);
+    TEST_INT_EQ(batch, (encoded[0] & 0x80), 0x80,
+                "Truly big-endian (IEEE 754 sign bit set for negative number)");
+    TEST_INT_EQ(batch, encoded[0], 0xC0,
+                "IEEE 754 representation of -2.0f, byte 0");
+    for (size_t i = 1; i < sizeof(float); i++) {
+        TEST_INT_EQ(batch, encoded[i], 0,
+                    "IEEE 754 representation of -2.0f, byte %d", (int)i);
+    }
+
+    FREEMEM(allocated);
+}
+
+static void
+test_bigend_f64(TestBatch *batch) {
+    double   source[]  = { -1.3, 0.0, 100.2 };
+    size_t   count     = 3;
+    size_t   amount    = (count + 1) * sizeof(double);
+    uint8_t *allocated = (uint8_t*)CALLOCATE(amount, sizeof(uint8_t));
+    uint8_t *encoded   = allocated + 1; // Intentionally misaligned.
+    uint8_t *target    = encoded;
+
+    for (size_t i = 0; i < count; i++) {
+        NumUtil_encode_bigend_f64(source[i], &target);
+        target += sizeof(double);
+    }
+    target = encoded;
+    for (size_t i = 0; i < count; i++) {
+        double got = NumUtil_decode_bigend_f64(target);
+        TEST_TRUE(batch, got == source[i], "bigend f64");
+        target += sizeof(double);
+    }
+
+    target = encoded;
+    NumUtil_encode_bigend_f64(-2.0, &target);
+    TEST_INT_EQ(batch, (encoded[0] & 0x80), 0x80,
+                "Truly big-endian (IEEE 754 sign bit set for negative number)");
+    TEST_INT_EQ(batch, encoded[0], 0xC0,
+                "IEEE 754 representation of -2.0, byte 0");
+    for (size_t i = 1; i < sizeof(double); i++) {
+        TEST_INT_EQ(batch, encoded[i], 0,
+                    "IEEE 754 representation of -2.0, byte %d", (int)i);
+    }
+
+    FREEMEM(allocated);
+}
+
+void
+TestNumUtil_run_tests(TestNumberUtils *self) {
+    TestBatch *batch = (TestBatch*)self;
+    srand((unsigned int)time((time_t*)NULL));
+    test_u1(batch);
+    test_u2(batch);
+    test_u4(batch);
+    test_c32(batch);
+    test_c64(batch);
+    test_bigend_u16(batch);
+    test_bigend_u32(batch);
+    test_bigend_u64(batch);
+    test_bigend_f32(batch);
+    test_bigend_f64(batch);
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/Util/TestNumberUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestNumberUtils.cfh b/core/Clownfish/Test/Util/TestNumberUtils.cfh
new file mode 100644
index 0000000..1c6659e
--- /dev/null
+++ b/core/Clownfish/Test/Util/TestNumberUtils.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::Util::TestNumberUtils cnick TestNumUtil
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestNumberUtils*
+    new(TestFormatter *formatter);
+
+    inert TestNumberUtils*
+    init(TestNumberUtils *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestNumberUtils *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/Util/TestStringHelper.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestStringHelper.c b/core/Clownfish/Test/Util/TestStringHelper.c
new file mode 100644
index 0000000..18cc4db
--- /dev/null
+++ b/core/Clownfish/Test/Util/TestStringHelper.c
@@ -0,0 +1,361 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/Util/TestStringHelper.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/Util/StringHelper.h"
+#include "Clownfish/VTable.h"
+#include "Lucy/Util/Json.h"
+#include "utf8proc.h"
+
+/* This alternative implementation of utf8_valid() is (presumably) slower, but
+ * it implements the standard in a more linear, easy-to-grok way.
+ */
+#define TRAIL_OK(n) (n >= 0x80 && n <= 0xBF)
+TestStringHelper*
+TestStrHelp_new(TestFormatter *formatter) {
+    TestStringHelper *self = (TestStringHelper*)VTable_Make_Obj(TESTSTRINGHELPER);
+    return TestStrHelp_init(self, formatter);
+}
+
+TestStringHelper*
+TestStrHelp_init(TestStringHelper *self, TestFormatter *formatter) {
+    return (TestStringHelper*)TestBatch_init((TestBatch*)self, 41, formatter);
+}
+
+static bool
+S_utf8_valid_alt(const char *maybe_utf8, size_t size) {
+    const uint8_t *string = (const uint8_t*)maybe_utf8;
+    const uint8_t *const end = string + size;
+    while (string < end) {
+        int count = StrHelp_UTF8_COUNT[*string];
+        bool valid = false;
+        if (count == 1) {
+            if (string[0] <= 0x7F) {
+                valid = true;
+            }
+        }
+        else if (count == 2) {
+            if (string[0] >= 0xC2 && string[0] <= 0xDF) {
+                if (TRAIL_OK(string[1])) {
+                    valid = true;
+                }
+            }
+        }
+        else if (count == 3) {
+            if (string[0] == 0xE0) {
+                if (string[1] >= 0xA0 && string[1] <= 0xBF
+                    && TRAIL_OK(string[2])
+                   ) {
+                    valid = true;
+                }
+            }
+            else if (string[0] >= 0xE1 && string[0] <= 0xEC) {
+                if (TRAIL_OK(string[1])
+                    && TRAIL_OK(string[2])
+                   ) {
+                    valid = true;
+                }
+            }
+            else if (string[0] == 0xED) {
+                if (string[1] >= 0x80 && string[1] <= 0x9F
+                    && TRAIL_OK(string[2])
+                   ) {
+                    valid = true;
+                }
+            }
+            else if (string[0] >= 0xEE && string[0] <= 0xEF) {
+                if (TRAIL_OK(string[1])
+                    && TRAIL_OK(string[2])
+                   ) {
+                    valid = true;
+                }
+            }
+        }
+        else if (count == 4) {
+            if (string[0] == 0xF0) {
+                if (string[1] >= 0x90 && string[1] <= 0xBF
+                    && TRAIL_OK(string[2])
+                    && TRAIL_OK(string[3])
+                   ) {
+                    valid = true;
+                }
+            }
+            else if (string[0] >= 0xF1 && string[0] <= 0xF3) {
+                if (TRAIL_OK(string[1])
+                    && TRAIL_OK(string[2])
+                    && TRAIL_OK(string[3])
+                   ) {
+                    valid = true;
+                }
+            }
+            else if (string[0] == 0xF4) {
+                if (string[1] >= 0x80 && string[1] <= 0x8F
+                    && TRAIL_OK(string[2])
+                    && TRAIL_OK(string[3])
+                   ) {
+                    valid = true;
+                }
+            }
+        }
+
+        if (!valid) {
+            return false;
+        }
+        string += count;
+    }
+
+    if (string != end) {
+        return false;
+    }
+
+    return true;
+}
+
+static void
+test_overlap(TestBatch *batch) {
+    int32_t result;
+    result = StrHelp_overlap("", "", 0, 0);
+    TEST_INT_EQ(batch, result, 0, "two empty strings");
+    result = StrHelp_overlap("", "foo", 0, 3);
+    TEST_INT_EQ(batch, result, 0, "first string is empty");
+    result = StrHelp_overlap("foo", "", 3, 0);
+    TEST_INT_EQ(batch, result, 0, "second string is empty");
+    result = StrHelp_overlap("foo", "foo", 3, 3);
+    TEST_INT_EQ(batch, result, 3, "equal strings");
+    result = StrHelp_overlap("foo bar", "foo", 7, 3);
+    TEST_INT_EQ(batch, result, 3, "first string is longer");
+    result = StrHelp_overlap("foo", "foo bar", 3, 7);
+    TEST_INT_EQ(batch, result, 3, "second string is longer");
+}
+
+
+static void
+test_to_base36(TestBatch *batch) {
+    char buffer[StrHelp_MAX_BASE36_BYTES];
+    StrHelp_to_base36(UINT64_MAX, buffer);
+    TEST_STR_EQ(batch, "3w5e11264sgsf", buffer, "base36 UINT64_MAX");
+    StrHelp_to_base36(1, buffer);
+    TEST_STR_EQ(batch, "1", buffer, "base36 1");
+    TEST_INT_EQ(batch, buffer[1], 0, "base36 NULL termination");
+}
+
+static void
+test_utf8_round_trip(TestBatch *batch) {
+    uint32_t code_point;
+    for (code_point = 0; code_point <= 0x10FFFF; code_point++) {
+        char buffer[4];
+        uint32_t size = StrHelp_encode_utf8_char(code_point, buffer);
+        char *start = buffer;
+        char *end   = start + size;
+
+        // Verify length returned by encode_utf8_char().
+        if (size != StrHelp_UTF8_COUNT[(unsigned char)buffer[0]]) {
+            break;
+        }
+        // Verify that utf8_valid() agrees with alternate implementation.
+        if (!!StrHelp_utf8_valid(start, size)
+            != !!S_utf8_valid_alt(start, size)
+           ) {
+            break;
+        }
+
+        // Verify back_utf8_char().
+        if (StrHelp_back_utf8_char(end, start) != start) {
+            break;
+        }
+
+        // Verify round trip of encode/decode.
+        if (StrHelp_decode_utf8_char(buffer) != code_point) {
+            break;
+        }
+    }
+    if (code_point == 0x110000) {
+        PASS(batch, "Successfully round tripped 0 - 0x10FFFF");
+    }
+    else {
+        FAIL(batch, "Failed round trip at 0x%.1X", (unsigned)code_point);
+    }
+}
+
+static void
+S_test_validity(TestBatch *batch, const char *content, size_t size,
+                bool expected, const char *description) {
+    bool sane = StrHelp_utf8_valid(content, size);
+    bool double_check = S_utf8_valid_alt(content, size);
+    if (sane != double_check) {
+        FAIL(batch, "Disagreement: %s", description);
+    }
+    else {
+        TEST_TRUE(batch, sane == expected, "%s", description);
+    }
+}
+
+static void
+test_utf8_valid(TestBatch *batch) {
+    // Musical symbol G clef:
+    // Code point: U+1D11E
+    // UTF-16:     0xD834 0xDD1E
+    // UTF-8       0xF0 0x9D 0x84 0x9E
+    S_test_validity(batch, "\xF0\x9D\x84\x9E", 4, true,
+                    "Musical symbol G clef");
+    S_test_validity(batch, "\xED\xA0\xB4\xED\xB4\x9E", 6, false,
+                    "G clef as UTF-8 encoded UTF-16 surrogates");
+    S_test_validity(batch, ".\xED\xA0\xB4.", 5, false,
+                    "Isolated high surrogate");
+    S_test_validity(batch, ".\xED\xB4\x9E.", 5, false,
+                    "Isolated low surrogate");
+
+    // Shortest form.
+    S_test_validity(batch, ".\xC1\x9C.", 4, false,
+                    "Non-shortest form ASCII backslash");
+    S_test_validity(batch, ".\xC0\xAF.", 4, false,
+                    "Non-shortest form ASCII slash");
+    S_test_validity(batch, ".\xC0\x80.", 4, false,
+                    "Non-shortest form ASCII NUL character");
+
+    // Range.
+    S_test_validity(batch, "\xF8\x88\x80\x80\x80", 5, false, "5-byte UTF-8");
+
+    // Bad continuations.
+    S_test_validity(batch, "\xE2\x98\xBA\xE2\x98\xBA", 6, true,
+                    "SmileySmiley");
+    S_test_validity(batch, "\xE2\xBA\xE2\x98\xBA", 5, false,
+                    "missing first continuation byte");
+    S_test_validity(batch, "\xE2\x98\xE2\x98\xBA", 5, false,
+                    "missing second continuation byte");
+    S_test_validity(batch, "\xE2\xE2\x98\xBA", 4, false,
+                    "missing both continuation bytes");
+    S_test_validity(batch, "\xBA\xE2\x98\xBA\xE2\xBA", 5, false,
+                    "missing first continuation byte (end)");
+    S_test_validity(batch, "\xE2\x98\xBA\xE2\x98", 5, false,
+                    "missing second continuation byte (end)");
+    S_test_validity(batch, "\xE2\x98\xBA\xE2", 4, false,
+                    "missing both continuation bytes (end)");
+    S_test_validity(batch, "\xBA\xE2\x98\xBA", 4, false,
+                    "isolated continuation byte 0xBA");
+    S_test_validity(batch, "\x98\xE2\x98\xBA", 4, false,
+                    "isolated continuation byte 0x98");
+    S_test_validity(batch, "\xE2\x98\xBA\xBA", 4, false,
+                    "isolated continuation byte 0xBA (end)");
+    S_test_validity(batch, "\xE2\x98\xBA\x98", 4, false,
+                    "isolated continuation byte 0x98 (end)");
+}
+
+static void
+test_is_whitespace(TestBatch *batch) {
+    TEST_TRUE(batch, StrHelp_is_whitespace(' '), "space is whitespace");
+    TEST_TRUE(batch, StrHelp_is_whitespace('\n'), "newline is whitespace");
+    TEST_TRUE(batch, StrHelp_is_whitespace('\t'), "tab is whitespace");
+    TEST_TRUE(batch, StrHelp_is_whitespace('\v'),
+              "vertical tab is whitespace");
+    TEST_TRUE(batch, StrHelp_is_whitespace(0x180E),
+              "Mongolian vowel separator is whitespace");
+    TEST_FALSE(batch, StrHelp_is_whitespace('a'), "'a' isn't whitespace");
+    TEST_FALSE(batch, StrHelp_is_whitespace(0), "NULL isn't whitespace");
+    TEST_FALSE(batch, StrHelp_is_whitespace(0x263A),
+               "Smiley isn't whitespace");
+}
+
+static void
+test_back_utf8_char(TestBatch *batch) {
+    char buffer[4];
+    char *buf = buffer + 1;
+    uint32_t len = StrHelp_encode_utf8_char(0x263A, buffer);
+    char *end = buffer + len;
+    TEST_TRUE(batch, StrHelp_back_utf8_char(end, buffer) == buffer,
+              "back_utf8_char");
+    TEST_TRUE(batch, StrHelp_back_utf8_char(end, buf) == NULL,
+              "back_utf8_char returns NULL rather than back up beyond start");
+    TEST_TRUE(batch, StrHelp_back_utf8_char(buffer, buffer) == NULL,
+              "back_utf8_char returns NULL when end == start");
+}
+
+static void
+test_utf8proc_normalization(TestBatch *batch) {
+    SKIP(batch, "utf8proc can't handle control chars or Unicode non-chars");
+    return;
+
+    for (int32_t i = 0; i < 100; i++) {
+        CharBuf *source = TestUtils_random_string(rand() % 40);
+
+        // Normalize once.
+        uint8_t *normalized;
+        int32_t check = utf8proc_map(CB_Get_Ptr8(source), CB_Get_Size(source),
+                                     &normalized,
+                                     UTF8PROC_STABLE  |
+                                     UTF8PROC_COMPOSE |
+                                     UTF8PROC_COMPAT  |
+                                     UTF8PROC_CASEFOLD);
+        if (check < 0) {
+            lucy_Json_set_tolerant(1);
+            CharBuf *json = lucy_Json_to_json((Obj*)source);
+            if (!json) {
+                json = CB_newf("[failed to encode]");
+            }
+            FAIL(batch, "Failed to normalize: %s", CB_Get_Ptr8(json));
+            DECREF(json);
+            DECREF(source);
+            return;
+        }
+
+        // Normalize again.
+        size_t normalized_len = strlen((char*)normalized);
+        uint8_t *dupe;
+        int32_t dupe_check = utf8proc_map(normalized, normalized_len, &dupe,
+                                          UTF8PROC_STABLE  |
+                                          UTF8PROC_COMPOSE |
+                                          UTF8PROC_COMPAT  |
+                                          UTF8PROC_CASEFOLD);
+        if (dupe_check < 0) {
+            THROW(ERR, "Unexpected normalization error: %i32", dupe_check);
+        }
+        int comparison = strcmp((char*)normalized, (char*)dupe);
+        free(dupe);
+        free(normalized);
+        DECREF(source);
+        if (comparison != 0) {
+            FAIL(batch, "Not fully normalized");
+            return;
+        }
+    }
+    PASS(batch, "Normalization successful.");
+}
+
+void
+TestStrHelp_run_tests(TestStringHelper *self) {
+    TestBatch *batch = (TestBatch*)self;
+    test_overlap(batch);
+    test_to_base36(batch);
+    test_utf8_round_trip(batch);
+    test_utf8_valid(batch);
+    test_is_whitespace(batch);
+    test_back_utf8_char(batch);
+    test_utf8proc_normalization(batch);
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Clownfish/Test/Util/TestStringHelper.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestStringHelper.cfh b/core/Clownfish/Test/Util/TestStringHelper.cfh
new file mode 100644
index 0000000..1c33ea5
--- /dev/null
+++ b/core/Clownfish/Test/Util/TestStringHelper.cfh
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel TestClownfish;
+
+class Clownfish::Test::Util::TestStringHelper cnick TestStrHelp
+    inherits Clownfish::Test::TestBatch {
+
+    inert incremented TestStringHelper*
+    new(TestFormatter *formatter);
+
+    inert TestStringHelper*
+    init(TestStringHelper *self, TestFormatter *formatter);
+
+    void
+    Run_Tests(TestStringHelper *self);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test.c b/core/Lucy/Test.c
index e9604e9..19fef0e 100644
--- a/core/Lucy/Test.c
+++ b/core/Lucy/Test.c
@@ -42,15 +42,7 @@
 #include "Lucy/Test/Index/TestSnapshot.h"
 #include "Lucy/Test/Index/TestTermInfo.h"
 #include "Lucy/Test/Object/TestBitVector.h"
-#include "Lucy/Test/Object/TestByteBuf.h"
-#include "Lucy/Test/Object/TestCharBuf.h"
-#include "Lucy/Test/Object/TestErr.h"
-#include "Lucy/Test/Object/TestHash.h"
 #include "Lucy/Test/Object/TestI32Array.h"
-#include "Lucy/Test/Object/TestLockFreeRegistry.h"
-#include "Lucy/Test/Object/TestNum.h"
-#include "Lucy/Test/Object/TestObj.h"
-#include "Lucy/Test/Object/TestVArray.h"
 #include "Lucy/Test/Plan/TestBlobType.h"
 #include "Lucy/Test/Plan/TestFieldMisc.h"
 #include "Lucy/Test/Plan/TestFieldType.h"
@@ -84,14 +76,10 @@
 #include "Lucy/Test/Store/TestRAMFileHandle.h"
 #include "Lucy/Test/Store/TestRAMFolder.h"
 #include "Lucy/Test/TestSchema.h"
-#include "Lucy/Test/Util/TestAtomic.h"
 #include "Lucy/Test/Util/TestIndexFileNames.h"
 #include "Lucy/Test/Util/TestJson.h"
-#include "Lucy/Test/Util/TestMemory.h"
 #include "Lucy/Test/Util/TestMemoryPool.h"
-#include "Lucy/Test/Util/TestNumberUtils.h"
 #include "Lucy/Test/Util/TestPriorityQueue.h"
-#include "Lucy/Test/Util/TestStringHelper.h"
 
 static void
 S_unbuffer_stdout();
@@ -102,22 +90,10 @@ S_all_test_batches(TestFormatter *formatter) {
 
     VA_Push(batches, (Obj*)TestPriQ_new(formatter));
     VA_Push(batches, (Obj*)TestBitVector_new(formatter));
-    VA_Push(batches, (Obj*)TestVArray_new(formatter));
-    VA_Push(batches, (Obj*)TestHash_new(formatter));
-    VA_Push(batches, (Obj*)TestObj_new(formatter));
-    VA_Push(batches, (Obj*)TestErr_new(formatter));
-    VA_Push(batches, (Obj*)TestBB_new(formatter));
     VA_Push(batches, (Obj*)TestMemPool_new(formatter));
-    VA_Push(batches, (Obj*)TestCB_new(formatter));
-    VA_Push(batches, (Obj*)TestNumUtil_new(formatter));
-    VA_Push(batches, (Obj*)TestNum_new(formatter));
-    VA_Push(batches, (Obj*)TestStrHelp_new(formatter));
     VA_Push(batches, (Obj*)TestIxFileNames_new(formatter));
     VA_Push(batches, (Obj*)TestJson_new(formatter));
     VA_Push(batches, (Obj*)TestI32Arr_new(formatter));
-    VA_Push(batches, (Obj*)TestAtomic_new(formatter));
-    VA_Push(batches, (Obj*)TestLFReg_new(formatter));
-    VA_Push(batches, (Obj*)TestMemory_new(formatter));
     VA_Push(batches, (Obj*)TestRAMFH_new(formatter));
     VA_Push(batches, (Obj*)TestFSFH_new(formatter));
     VA_Push(batches, (Obj*)TestInStream_new(formatter));

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestByteBuf.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestByteBuf.c b/core/Lucy/Test/Object/TestByteBuf.c
deleted file mode 100644
index 9143b56..0000000
--- a/core/Lucy/Test/Object/TestByteBuf.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_LUCY_TESTBYTEBUF
-#include "Lucy/Util/ToolSet.h"
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/TestUtils.h"
-#include "Lucy/Test/Object/TestByteBuf.h"
-
-TestByteBuf*
-TestBB_new(TestFormatter *formatter) {
-    TestByteBuf *self = (TestByteBuf*)VTable_Make_Obj(TESTBYTEBUF);
-    return TestBB_init(self, formatter);
-}
-
-TestByteBuf*
-TestBB_init(TestByteBuf *self, TestFormatter *formatter) {
-    return (TestByteBuf*)TestBatch_init((TestBatch*)self, 22, formatter);
-}
-
-static void
-test_Equals(TestBatch *batch) {
-    ByteBuf *wanted = BB_new_bytes("foo", 4); // Include terminating NULL.
-    ByteBuf *got    = BB_new_bytes("foo", 4);
-
-    TEST_TRUE(batch, BB_Equals(wanted, (Obj*)got), "Equals");
-    TEST_INT_EQ(batch, BB_Hash_Sum(got), BB_Hash_Sum(wanted), "Hash_Sum");
-
-    TEST_TRUE(batch, BB_Equals_Bytes(got, "foo", 4), "Equals_Bytes");
-    TEST_FALSE(batch, BB_Equals_Bytes(got, "foo", 3),
-               "Equals_Bytes spoiled by different size");
-    TEST_FALSE(batch, BB_Equals_Bytes(got, "bar", 4),
-               "Equals_Bytes spoiled by different content");
-
-    BB_Set_Size(got, 3);
-    TEST_FALSE(batch, BB_Equals(wanted, (Obj*)got),
-               "Different size spoils Equals");
-    TEST_FALSE(batch, BB_Hash_Sum(got) == BB_Hash_Sum(wanted),
-               "Different size spoils Hash_Sum (probably -- at least this one)");
-
-    BB_Mimic_Bytes(got, "bar", 4);
-    TEST_INT_EQ(batch, BB_Get_Size(wanted), BB_Get_Size(got),
-                "same length");
-    TEST_FALSE(batch, BB_Equals(wanted, (Obj*)got),
-               "Different content spoils Equals");
-
-    DECREF(got);
-    DECREF(wanted);
-}
-
-static void
-test_Grow(TestBatch *batch) {
-    ByteBuf *bb = BB_new(1);
-    TEST_INT_EQ(batch, BB_Get_Capacity(bb), 8,
-                "Allocate in 8-byte increments");
-    BB_Grow(bb, 9);
-    TEST_INT_EQ(batch, BB_Get_Capacity(bb), 16,
-                "Grow in 8-byte increments");
-    DECREF(bb);
-}
-
-static void
-test_Clone(TestBatch *batch) {
-    ByteBuf *bb = BB_new_bytes("foo", 3);
-    ByteBuf *twin = BB_Clone(bb);
-    TEST_TRUE(batch, BB_Equals(bb, (Obj*)twin), "Clone");
-    DECREF(bb);
-    DECREF(twin);
-}
-
-static void
-test_compare(TestBatch *batch) {
-    ByteBuf *a = BB_new_bytes("foo\0a", 5);
-    ByteBuf *b = BB_new_bytes("foo\0b", 5);
-
-    BB_Set_Size(a, 4);
-    BB_Set_Size(b, 4);
-    TEST_INT_EQ(batch, BB_compare(&a, &b), 0,
-                "BB_compare returns 0 for equal ByteBufs");
-
-    BB_Set_Size(a, 3);
-    TEST_TRUE(batch, BB_compare(&a, &b) < 0, "shorter ByteBuf sorts first");
-
-    BB_Set_Size(a, 5);
-    BB_Set_Size(b, 5);
-    TEST_TRUE(batch, BB_compare(&a, &b) < 0,
-              "NULL doesn't interfere with BB_compare");
-
-    DECREF(a);
-    DECREF(b);
-}
-
-static void
-test_Mimic(TestBatch *batch) {
-    ByteBuf *a = BB_new_bytes("foo", 3);
-    ByteBuf *b = BB_new(0);
-
-    BB_Mimic(b, (Obj*)a);
-    TEST_TRUE(batch, BB_Equals(a, (Obj*)b), "Mimic");
-
-    BB_Mimic_Bytes(a, "bar", 4);
-    TEST_TRUE(batch, strcmp(BB_Get_Buf(a), "bar") == 0,
-              "Mimic_Bytes content");
-    TEST_INT_EQ(batch, BB_Get_Size(a), 4, "Mimic_Bytes size");
-
-    BB_Mimic(b, (Obj*)a);
-    TEST_TRUE(batch, BB_Equals(a, (Obj*)b), "Mimic");
-
-    DECREF(a);
-    DECREF(b);
-}
-
-static void
-test_Cat(TestBatch *batch) {
-    ByteBuf *wanted  = BB_new_bytes("foobar", 6);
-    ByteBuf *got     = BB_new_bytes("foo", 3);
-    ByteBuf *scratch = BB_new_bytes("bar", 3);
-
-    BB_Cat(got, scratch);
-    TEST_TRUE(batch, BB_Equals(wanted, (Obj*)got), "Cat");
-
-    BB_Mimic_Bytes(wanted, "foobarbaz", 9);
-    BB_Cat_Bytes(got, "baz", 3);
-    TEST_TRUE(batch, BB_Equals(wanted, (Obj*)got), "Cat_Bytes");
-
-    DECREF(scratch);
-    DECREF(got);
-    DECREF(wanted);
-}
-
-static void
-test_serialization(TestBatch *batch) {
-    ByteBuf *wanted = BB_new_bytes("foobar", 6);
-    ByteBuf *got    = (ByteBuf*)TestUtils_freeze_thaw((Obj*)wanted);
-    TEST_TRUE(batch, got && BB_Equals(wanted, (Obj*)got),
-              "Serialization round trip");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-void
-TestBB_run_tests(TestByteBuf *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Equals(batch);
-    test_Grow(batch);
-    test_Clone(batch);
-    test_compare(batch);
-    test_Mimic(batch);
-    test_Cat(batch);
-    test_serialization(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestByteBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestByteBuf.cfh b/core/Lucy/Test/Object/TestByteBuf.cfh
deleted file mode 100644
index ad4fabe..0000000
--- a/core/Lucy/Test/Object/TestByteBuf.cfh
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-parcel Lucy;
-
-class Lucy::Test::Object::TestByteBuf cnick TestBB
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestByteBuf*
-    new(TestFormatter *formatter);
-
-    inert TestByteBuf*
-    init(TestByteBuf *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestByteBuf *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestCharBuf.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestCharBuf.c b/core/Lucy/Test/Object/TestCharBuf.c
deleted file mode 100644
index 1e95345..0000000
--- a/core/Lucy/Test/Object/TestCharBuf.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_LUCY_TESTCHARBUF
-#include "Lucy/Util/ToolSet.h"
-#include <string.h>
-#include <stdio.h>
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/TestUtils.h"
-#include "Lucy/Test/Object/TestCharBuf.h"
-
-static char smiley[] = { (char)0xE2, (char)0x98, (char)0xBA, 0 };
-static uint32_t smiley_len = 3;
-
-TestCharBuf*
-TestCB_new(TestFormatter *formatter) {
-    TestCharBuf *self = (TestCharBuf*)VTable_Make_Obj(TESTCHARBUF);
-    return TestCB_init(self, formatter);
-}
-
-TestCharBuf*
-TestCB_init(TestCharBuf *self, TestFormatter *formatter) {
-    return (TestCharBuf*)TestBatch_init((TestBatch*)self, 55, formatter);
-}
-
-static CharBuf*
-S_get_cb(const char *string) {
-    return CB_new_from_utf8(string, strlen(string));
-}
-
-static void
-test_Cat(TestBatch *batch) {
-    CharBuf *wanted = CB_newf("a%s", smiley);
-    CharBuf *got    = S_get_cb("");
-
-    CB_Cat(got, wanted);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat");
-    DECREF(got);
-
-    got = S_get_cb("a");
-    CB_Cat_Char(got, 0x263A);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Char");
-    DECREF(got);
-
-    got = S_get_cb("a");
-    CB_Cat_Str(got, smiley, smiley_len);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Str");
-    DECREF(got);
-
-    got = S_get_cb("a");
-    CB_Cat_Trusted_Str(got, smiley, smiley_len);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Trusted_Str");
-    DECREF(got);
-
-    DECREF(wanted);
-}
-
-static void
-test_Mimic_and_Clone(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo");
-    CharBuf *got    = S_get_cb("bar");
-
-    CB_Mimic(got, (Obj*)wanted);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Mimic");
-    DECREF(got);
-
-    got = S_get_cb("bar");
-    CB_Mimic_Str(got, "foo", 3);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Mimic_Str");
-    DECREF(got);
-
-    got = CB_Clone(wanted);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Clone");
-    DECREF(got);
-
-    DECREF(wanted);
-}
-
-static void
-test_Find(TestBatch *batch) {
-    CharBuf *string = CB_new(10);
-    CharBuf *substring = S_get_cb("foo");
-
-    TEST_TRUE(batch, CB_Find(string, substring) == -1, "Not in empty string");
-    CB_setf(string, "foo");
-    TEST_TRUE(batch, CB_Find(string, substring) == 0, "Find complete string");
-    CB_setf(string, "afoo");
-    TEST_TRUE(batch, CB_Find(string, substring) == 1, "Find after first");
-    CB_Set_Size(string, 3);
-    TEST_TRUE(batch, CB_Find(string, substring) == -1, "Don't overrun");
-    CB_setf(string, "afood");
-    TEST_TRUE(batch, CB_Find(string, substring) == 1, "Find in middle");
-
-    DECREF(substring);
-    DECREF(string);
-}
-
-static void
-test_Code_Point_At_and_From(TestBatch *batch) {
-    uint32_t code_points[] = { 'a', 0x263A, 0x263A, 'b', 0x263A, 'c' };
-    uint32_t num_code_points = sizeof(code_points) / sizeof(uint32_t);
-    CharBuf *string = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
-    uint32_t i;
-
-    for (i = 0; i < num_code_points; i++) {
-        uint32_t from = num_code_points - i - 1;
-        TEST_INT_EQ(batch, CB_Code_Point_At(string, i), code_points[i],
-                    "Code_Point_At %ld", (long)i);
-        TEST_INT_EQ(batch, CB_Code_Point_At(string, from),
-                    code_points[from], "Code_Point_From %ld", (long)from);
-    }
-
-    DECREF(string);
-}
-
-static void
-test_SubString(TestBatch *batch) {
-    CharBuf *string = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
-    CharBuf *wanted = CB_newf("%sb%s", smiley, smiley);
-    CharBuf *got = CB_SubString(string, 2, 3);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "SubString");
-    DECREF(wanted);
-    DECREF(got);
-    DECREF(string);
-}
-
-static void
-test_Nip_and_Chop(TestBatch *batch) {
-    CharBuf *wanted;
-    CharBuf *got;
-
-    wanted = CB_newf("%sb%sc", smiley, smiley);
-    got    = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
-    CB_Nip(got, 2);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Nip");
-    DECREF(wanted);
-    DECREF(got);
-
-    wanted = CB_newf("a%s%s", smiley, smiley);
-    got    = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
-    CB_Chop(got, 3);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Chop");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-
-static void
-test_Truncate(TestBatch *batch) {
-    CharBuf *wanted = CB_newf("a%s", smiley, smiley);
-    CharBuf *got    = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
-    CB_Truncate(got, 2);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Truncate");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_Trim(TestBatch *batch) {
-    uint32_t spaces[] = {
-        ' ',    '\t',   '\r',   '\n',   0x000B, 0x000C, 0x000D, 0x0085,
-        0x00A0, 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004,
-        0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029,
-        0x202F, 0x205F, 0x3000
-    };
-    uint32_t num_spaces = sizeof(spaces) / sizeof(uint32_t);
-    uint32_t i;
-    CharBuf *got = CB_new(0);
-
-    // Surround a smiley with lots of whitespace.
-    for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
-    CB_Cat_Char(got, 0x263A);
-    for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
-
-    TEST_TRUE(batch, CB_Trim_Top(got), "Trim_Top returns true on success");
-    TEST_FALSE(batch, CB_Trim_Top(got),
-               "Trim_Top returns false on failure");
-    TEST_TRUE(batch, CB_Trim_Tail(got), "Trim_Tail returns true on success");
-    TEST_FALSE(batch, CB_Trim_Tail(got),
-               "Trim_Tail returns false on failure");
-    TEST_TRUE(batch, CB_Equals_Str(got, smiley, smiley_len),
-              "Trim_Top and Trim_Tail worked");
-
-    // Build the spacey smiley again.
-    CB_Truncate(got, 0);
-    for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
-    CB_Cat_Char(got, 0x263A);
-    for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
-
-    TEST_TRUE(batch, CB_Trim(got), "Trim returns true on success");
-    TEST_FALSE(batch, CB_Trim(got), "Trim returns false on failure");
-    TEST_TRUE(batch, CB_Equals_Str(got, smiley, smiley_len),
-              "Trim worked");
-
-    DECREF(got);
-}
-
-static void
-test_To_F64(TestBatch *batch) {
-    CharBuf *charbuf = S_get_cb("1.5");
-    double difference = 1.5 - CB_To_F64(charbuf);
-    if (difference < 0) { difference = 0 - difference; }
-    TEST_TRUE(batch, difference < 0.001, "To_F64");
-
-    CB_setf(charbuf, "-1.5");
-    difference = 1.5 + CB_To_F64(charbuf);
-    if (difference < 0) { difference = 0 - difference; }
-    TEST_TRUE(batch, difference < 0.001, "To_F64 negative");
-
-    CB_setf(charbuf, "1.59");
-    double value_full = CB_To_F64(charbuf);
-    CB_Set_Size(charbuf, 3);
-    double value_short = CB_To_F64(charbuf);
-    TEST_TRUE(batch, value_short < value_full,
-              "TO_F64 doesn't run past end of string");
-
-    DECREF(charbuf);
-}
-
-static void
-test_To_I64(TestBatch *batch) {
-    CharBuf *charbuf = S_get_cb("10");
-    TEST_TRUE(batch, CB_To_I64(charbuf) == 10, "To_I64");
-    CB_setf(charbuf, "-10");
-    TEST_TRUE(batch, CB_To_I64(charbuf) == -10, "To_I64 negative");
-    DECREF(charbuf);
-}
-
-
-static void
-test_vcatf_s(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar bizzle baz");
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %s baz", "bizzle");
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%s");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_null_string(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar [NULL] baz");
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %s baz", NULL);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%s NULL");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_cb(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar ZEKE baz");
-    CharBuf *catworthy = S_get_cb("ZEKE");
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %o baz", catworthy);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o CharBuf");
-    DECREF(catworthy);
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_obj(TestBatch *batch) {
-    CharBuf   *wanted = S_get_cb("ooga 20 booga");
-    Integer32 *i32 = Int32_new(20);
-    CharBuf   *got = S_get_cb("ooga");
-    CB_catf(got, " %o booga", i32);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o Obj");
-    DECREF(i32);
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_null_obj(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar [NULL] baz");
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %o baz", NULL);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o NULL");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_i8(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar -3 baz");
-    int8_t num = -3;
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %i8 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%i8");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_i32(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar -100000 baz");
-    int32_t num = -100000;
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %i32 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%i32");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_i64(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar -5000000000 baz");
-    int64_t num = INT64_C(-5000000000);
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %i64 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%i64");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_u8(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar 3 baz");
-    uint8_t num = 3;
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %u8 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u8");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_u32(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar 100000 baz");
-    uint32_t num = 100000;
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %u32 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u32");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_u64(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo bar 5000000000 baz");
-    uint64_t num = UINT64_C(5000000000);
-    CharBuf *got = S_get_cb("foo ");
-    CB_catf(got, "bar %u64 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u64");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_f64(TestBatch *batch) {
-    CharBuf *wanted;
-    char buf[64];
-    float num = 1.3f;
-    CharBuf *got = S_get_cb("foo ");
-    sprintf(buf, "foo bar %g baz", num);
-    wanted = CB_new_from_trusted_utf8(buf, strlen(buf));
-    CB_catf(got, "bar %f64 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%f64");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_vcatf_x32(TestBatch *batch) {
-    CharBuf *wanted;
-    char buf[64];
-    unsigned long num = INT32_MAX;
-    CharBuf *got = S_get_cb("foo ");
-#if (SIZEOF_LONG == 4)
-    sprintf(buf, "foo bar %.8lx baz", num);
-#elif (SIZEOF_INT == 4)
-    sprintf(buf, "foo bar %.8x baz", (unsigned)num);
-#endif
-    wanted = CB_new_from_trusted_utf8(buf, strlen(buf));
-    CB_catf(got, "bar %x32 baz", (uint32_t)num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%x32");
-    DECREF(wanted);
-    DECREF(got);
-}
-
-static void
-test_serialization(TestBatch *batch) {
-    CharBuf *wanted = S_get_cb("foo");
-    CharBuf *got    = (CharBuf*)TestUtils_freeze_thaw((Obj*)wanted);
-    TEST_TRUE(batch, got && CB_Equals(wanted, (Obj*)got),
-              "Round trip through FREEZE/THAW");
-    DECREF(got);
-    DECREF(wanted);
-}
-
-void
-TestCB_run_tests(TestCharBuf *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_vcatf_s(batch);
-    test_vcatf_null_string(batch);
-    test_vcatf_cb(batch);
-    test_vcatf_obj(batch);
-    test_vcatf_null_obj(batch);
-    test_vcatf_i8(batch);
-    test_vcatf_i32(batch);
-    test_vcatf_i64(batch);
-    test_vcatf_u8(batch);
-    test_vcatf_u32(batch);
-    test_vcatf_u64(batch);
-    test_vcatf_f64(batch);
-    test_vcatf_x32(batch);
-    test_Cat(batch);
-    test_Mimic_and_Clone(batch);
-    test_Code_Point_At_and_From(batch);
-    test_Find(batch);
-    test_SubString(batch);
-    test_Nip_and_Chop(batch);
-    test_Truncate(batch);
-    test_Trim(batch);
-    test_To_F64(batch);
-    test_To_I64(batch);
-    test_serialization(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestCharBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestCharBuf.cfh b/core/Lucy/Test/Object/TestCharBuf.cfh
deleted file mode 100644
index 0e70e40..0000000
--- a/core/Lucy/Test/Object/TestCharBuf.cfh
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-parcel Lucy;
-
-class Lucy::Test::Object::TestCharBuf cnick TestCB
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestCharBuf*
-    new(TestFormatter *formatter);
-
-    inert TestCharBuf*
-    init(TestCharBuf *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestCharBuf *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestErr.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestErr.c b/core/Lucy/Test/Object/TestErr.c
deleted file mode 100644
index 5cbd365..0000000
--- a/core/Lucy/Test/Object/TestErr.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Lucy/Util/ToolSet.h"
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Lucy/Test.h"
-#include "Lucy/Test/TestUtils.h"
-#include "Lucy/Test/Object/TestErr.h"
-#include "Clownfish/Err.h"
-
-TestErr*
-TestErr_new(TestFormatter *formatter) {
-    TestErr *self = (TestErr*)VTable_Make_Obj(TESTERR);
-    return TestErr_init(self, formatter);
-}
-
-TestErr*
-TestErr_init(TestErr *self, TestFormatter *formatter) {
-    return (TestErr*)TestBatch_init((TestBatch*)self, 1, formatter);
-}
-
-static void
-test_To_String(TestBatch *batch) {
-    CharBuf *message = CB_newf("oops");
-    Err *error = Err_new(message);
-    CharBuf *string = Err_To_String(error);
-    TEST_TRUE(batch, CB_Equals(message, (Obj*)string),
-              "Stringifies as message");
-    DECREF(string);
-    DECREF(error);
-}
-
-void
-TestErr_run_tests(TestErr *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_To_String(batch);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/9f826b31/core/Lucy/Test/Object/TestErr.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestErr.cfh b/core/Lucy/Test/Object/TestErr.cfh
deleted file mode 100644
index 316512f..0000000
--- a/core/Lucy/Test/Object/TestErr.cfh
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Lucy;
-
-class Lucy::Test::Object::TestErr
-    inherits Clownfish::Test::TestBatch {
-
-    inert incremented TestErr*
-    new(TestFormatter *formatter);
-
-    inert TestErr*
-    init(TestErr *self, TestFormatter *formatter);
-
-    void
-    Run_Tests(TestErr *self);
-}
-


[lucy-commits] [03/26] git commit: refs/heads/separate-clownfish-wip2 - Don't include charmony.h from boot.c

Posted by nw...@apache.org.
Don't include charmony.h from boot.c


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/f1c98421
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/f1c98421
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/f1c98421

Branch: refs/heads/separate-clownfish-wip2
Commit: f1c98421ae55f335cfec8fd0b92829d51e137a8b
Parents: ec363b1
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat May 25 18:48:55 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:16 2013 +0200

----------------------------------------------------------------------
 clownfish/compiler/src/CFCPerl.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/f1c98421/clownfish/compiler/src/CFCPerl.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCPerl.c b/clownfish/compiler/src/CFCPerl.c
index 80d0c1b..c7f971b 100644
--- a/clownfish/compiler/src/CFCPerl.c
+++ b/clownfish/compiler/src/CFCPerl.c
@@ -283,7 +283,6 @@ S_write_boot_c(CFCPerl *self) {
     const char pattern[] =
         "%s\n"
         "\n"
-        "#include \"charmony.h\"\n"
         "#include \"%s\"\n"
         "#include \"EXTERN.h\"\n"
         "#include \"perl.h\"\n"


[lucy-commits] [16/26] git commit: refs/heads/separate-clownfish-wip2 - Move test harness classes to Clownfish::TestHarness

Posted by nw...@apache.org.
Move test harness classes to Clownfish::TestHarness


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/d4d7d029
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/d4d7d029
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/d4d7d029

Branch: refs/heads/separate-clownfish-wip2
Commit: d4d7d02929fa41602d02ebc6f63894e2ac44467f
Parents: ffb0e92
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 27 22:35:30 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:32:00 2013 +0200

----------------------------------------------------------------------
 c/t/test_lucy.c                                    |    2 +-
 core/Clownfish/Test.c                              |    6 +-
 core/Clownfish/Test/TestBatch.c                    |  293 ---------------
 core/Clownfish/Test/TestBatch.cfh                  |  120 ------
 core/Clownfish/Test/TestByteBuf.c                  |    4 +-
 core/Clownfish/Test/TestByteBuf.cfh                |    2 +-
 core/Clownfish/Test/TestCharBuf.c                  |    4 +-
 core/Clownfish/Test/TestCharBuf.cfh                |    2 +-
 core/Clownfish/Test/TestErr.c                      |    2 +-
 core/Clownfish/Test/TestErr.cfh                    |    2 +-
 core/Clownfish/Test/TestFormatter.c                |  184 ---------
 core/Clownfish/Test/TestFormatter.cfh              |  138 -------
 core/Clownfish/Test/TestHash.c                     |    4 +-
 core/Clownfish/Test/TestHash.cfh                   |    2 +-
 core/Clownfish/Test/TestLockFreeRegistry.c         |    2 +-
 core/Clownfish/Test/TestLockFreeRegistry.cfh       |    2 +-
 core/Clownfish/Test/TestNum.c                      |    4 +-
 core/Clownfish/Test/TestNum.cfh                    |    2 +-
 core/Clownfish/Test/TestObj.c                      |    2 +-
 core/Clownfish/Test/TestObj.cfh                    |    2 +-
 core/Clownfish/Test/TestRunner.c                   |   93 -----
 core/Clownfish/Test/TestRunner.cfh                 |   77 ----
 core/Clownfish/Test/TestUtils.c                    |  140 -------
 core/Clownfish/Test/TestUtils.cfh                  |   71 ----
 core/Clownfish/Test/TestVArray.c                   |    4 +-
 core/Clownfish/Test/TestVArray.cfh                 |    2 +-
 core/Clownfish/Test/Util/TestAtomic.c              |    2 +-
 core/Clownfish/Test/Util/TestAtomic.cfh            |    2 +-
 core/Clownfish/Test/Util/TestMemory.c              |    2 +-
 core/Clownfish/Test/Util/TestMemory.cfh            |    2 +-
 core/Clownfish/Test/Util/TestNumberUtils.c         |    4 +-
 core/Clownfish/Test/Util/TestNumberUtils.cfh       |    2 +-
 core/Clownfish/Test/Util/TestStringHelper.c        |    4 +-
 core/Clownfish/Test/Util/TestStringHelper.cfh      |    2 +-
 core/Clownfish/TestHarness/TestBatch.c             |  293 +++++++++++++++
 core/Clownfish/TestHarness/TestBatch.cfh           |  120 ++++++
 core/Clownfish/TestHarness/TestFormatter.c         |  184 +++++++++
 core/Clownfish/TestHarness/TestFormatter.cfh       |  138 +++++++
 core/Clownfish/TestHarness/TestRunner.c            |   93 +++++
 core/Clownfish/TestHarness/TestRunner.cfh          |   77 ++++
 core/Clownfish/TestHarness/TestUtils.c             |  140 +++++++
 core/Clownfish/TestHarness/TestUtils.cfh           |   71 ++++
 core/Lucy/Test.c                                   |    6 +-
 core/Lucy/Test/Analysis/TestAnalyzer.c             |    2 +-
 core/Lucy/Test/Analysis/TestAnalyzer.cfh           |    2 +-
 core/Lucy/Test/Analysis/TestCaseFolder.c           |    2 +-
 core/Lucy/Test/Analysis/TestCaseFolder.cfh         |    2 +-
 core/Lucy/Test/Analysis/TestNormalizer.c           |    2 +-
 core/Lucy/Test/Analysis/TestNormalizer.cfh         |    2 +-
 core/Lucy/Test/Analysis/TestPolyAnalyzer.c         |    2 +-
 core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh       |    2 +-
 core/Lucy/Test/Analysis/TestRegexTokenizer.c       |    2 +-
 core/Lucy/Test/Analysis/TestRegexTokenizer.cfh     |    2 +-
 core/Lucy/Test/Analysis/TestSnowballStemmer.c      |    2 +-
 core/Lucy/Test/Analysis/TestSnowballStemmer.cfh    |    2 +-
 core/Lucy/Test/Analysis/TestSnowballStopFilter.c   |    2 +-
 core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh |    2 +-
 core/Lucy/Test/Analysis/TestStandardTokenizer.c    |    2 +-
 core/Lucy/Test/Analysis/TestStandardTokenizer.cfh  |    2 +-
 core/Lucy/Test/Highlight/TestHeatMap.c             |    2 +-
 core/Lucy/Test/Highlight/TestHeatMap.cfh           |    2 +-
 core/Lucy/Test/Highlight/TestHighlighter.c         |    2 +-
 core/Lucy/Test/Highlight/TestHighlighter.cfh       |    2 +-
 core/Lucy/Test/Index/TestDocWriter.c               |    2 +-
 core/Lucy/Test/Index/TestDocWriter.cfh             |    2 +-
 core/Lucy/Test/Index/TestHighlightWriter.c         |    2 +-
 core/Lucy/Test/Index/TestHighlightWriter.cfh       |    2 +-
 core/Lucy/Test/Index/TestIndexManager.c            |    2 +-
 core/Lucy/Test/Index/TestIndexManager.cfh          |    2 +-
 core/Lucy/Test/Index/TestPolyReader.c              |    2 +-
 core/Lucy/Test/Index/TestPolyReader.cfh            |    2 +-
 core/Lucy/Test/Index/TestPostingListWriter.c       |    2 +-
 core/Lucy/Test/Index/TestPostingListWriter.cfh     |    2 +-
 core/Lucy/Test/Index/TestSegWriter.c               |    2 +-
 core/Lucy/Test/Index/TestSegWriter.cfh             |    2 +-
 core/Lucy/Test/Index/TestSegment.c                 |    2 +-
 core/Lucy/Test/Index/TestSegment.cfh               |    2 +-
 core/Lucy/Test/Index/TestSnapshot.c                |    2 +-
 core/Lucy/Test/Index/TestSnapshot.cfh              |    2 +-
 core/Lucy/Test/Index/TestTermInfo.c                |    2 +-
 core/Lucy/Test/Index/TestTermInfo.cfh              |    2 +-
 core/Lucy/Test/Object/TestBitVector.c              |    2 +-
 core/Lucy/Test/Object/TestBitVector.cfh            |    2 +-
 core/Lucy/Test/Object/TestI32Array.c               |    2 +-
 core/Lucy/Test/Object/TestI32Array.cfh             |    2 +-
 core/Lucy/Test/Plan/TestBlobType.c                 |    2 +-
 core/Lucy/Test/Plan/TestBlobType.cfh               |    2 +-
 core/Lucy/Test/Plan/TestFieldMisc.c                |    2 +-
 core/Lucy/Test/Plan/TestFieldMisc.cfh              |    2 +-
 core/Lucy/Test/Plan/TestFieldType.c                |    2 +-
 core/Lucy/Test/Plan/TestFieldType.cfh              |    2 +-
 core/Lucy/Test/Plan/TestFullTextType.c             |    2 +-
 core/Lucy/Test/Plan/TestFullTextType.cfh           |    2 +-
 core/Lucy/Test/Plan/TestNumericType.c              |    2 +-
 core/Lucy/Test/Plan/TestNumericType.cfh            |    2 +-
 core/Lucy/Test/Search/TestLeafQuery.c              |    2 +-
 core/Lucy/Test/Search/TestLeafQuery.cfh            |    2 +-
 core/Lucy/Test/Search/TestMatchAllQuery.c          |    2 +-
 core/Lucy/Test/Search/TestMatchAllQuery.cfh        |    2 +-
 core/Lucy/Test/Search/TestNOTQuery.c               |    2 +-
 core/Lucy/Test/Search/TestNOTQuery.cfh             |    2 +-
 core/Lucy/Test/Search/TestNoMatchQuery.c           |    2 +-
 core/Lucy/Test/Search/TestNoMatchQuery.cfh         |    2 +-
 core/Lucy/Test/Search/TestPhraseQuery.c            |    2 +-
 core/Lucy/Test/Search/TestPhraseQuery.cfh          |    2 +-
 core/Lucy/Test/Search/TestPolyQuery.c              |    2 +-
 core/Lucy/Test/Search/TestPolyQuery.cfh            |    4 +-
 core/Lucy/Test/Search/TestQueryParserLogic.c       |    2 +-
 core/Lucy/Test/Search/TestQueryParserLogic.cfh     |    2 +-
 core/Lucy/Test/Search/TestQueryParserSyntax.c      |    2 +-
 core/Lucy/Test/Search/TestQueryParserSyntax.cfh    |    2 +-
 core/Lucy/Test/Search/TestRangeQuery.c             |    2 +-
 core/Lucy/Test/Search/TestRangeQuery.cfh           |    2 +-
 core/Lucy/Test/Search/TestReqOptQuery.c            |    2 +-
 core/Lucy/Test/Search/TestReqOptQuery.cfh          |    2 +-
 core/Lucy/Test/Search/TestSeriesMatcher.c          |    2 +-
 core/Lucy/Test/Search/TestSeriesMatcher.cfh        |    2 +-
 core/Lucy/Test/Search/TestSortSpec.c               |    2 +-
 core/Lucy/Test/Search/TestSortSpec.cfh             |    2 +-
 core/Lucy/Test/Search/TestSpan.c                   |    2 +-
 core/Lucy/Test/Search/TestSpan.cfh                 |    2 +-
 core/Lucy/Test/Search/TestTermQuery.c              |    2 +-
 core/Lucy/Test/Search/TestTermQuery.cfh            |    2 +-
 core/Lucy/Test/Store/TestCompoundFileReader.c      |    2 +-
 core/Lucy/Test/Store/TestCompoundFileReader.cfh    |    2 +-
 core/Lucy/Test/Store/TestCompoundFileWriter.c      |    2 +-
 core/Lucy/Test/Store/TestCompoundFileWriter.cfh    |    2 +-
 core/Lucy/Test/Store/TestFSDirHandle.c             |    2 +-
 core/Lucy/Test/Store/TestFSDirHandle.cfh           |    2 +-
 core/Lucy/Test/Store/TestFSFileHandle.c            |    2 +-
 core/Lucy/Test/Store/TestFSFileHandle.cfh          |    2 +-
 core/Lucy/Test/Store/TestFSFolder.c                |    2 +-
 core/Lucy/Test/Store/TestFSFolder.cfh              |    2 +-
 core/Lucy/Test/Store/TestFileHandle.c              |    2 +-
 core/Lucy/Test/Store/TestFileHandle.cfh            |    2 +-
 core/Lucy/Test/Store/TestFolder.c                  |    2 +-
 core/Lucy/Test/Store/TestFolder.cfh                |    2 +-
 core/Lucy/Test/Store/TestFolderCommon.c            |    2 +-
 core/Lucy/Test/Store/TestIOChunks.c                |    2 +-
 core/Lucy/Test/Store/TestIOChunks.cfh              |    2 +-
 core/Lucy/Test/Store/TestIOPrimitives.c            |    2 +-
 core/Lucy/Test/Store/TestIOPrimitives.cfh          |    2 +-
 core/Lucy/Test/Store/TestInStream.c                |    2 +-
 core/Lucy/Test/Store/TestInStream.cfh              |    2 +-
 core/Lucy/Test/Store/TestRAMDirHandle.c            |    2 +-
 core/Lucy/Test/Store/TestRAMDirHandle.cfh          |    2 +-
 core/Lucy/Test/Store/TestRAMFileHandle.c           |    2 +-
 core/Lucy/Test/Store/TestRAMFileHandle.cfh         |    2 +-
 core/Lucy/Test/Store/TestRAMFolder.c               |    2 +-
 core/Lucy/Test/Store/TestRAMFolder.cfh             |    2 +-
 core/Lucy/Test/TestSchema.c                        |    2 +-
 core/Lucy/Test/TestSchema.cfh                      |    2 +-
 core/Lucy/Test/TestUtils.c                         |    2 +-
 core/Lucy/Test/Util/TestIndexFileNames.c           |    2 +-
 core/Lucy/Test/Util/TestIndexFileNames.cfh         |    2 +-
 core/Lucy/Test/Util/TestJson.c                     |    2 +-
 core/Lucy/Test/Util/TestJson.cfh                   |    2 +-
 core/Lucy/Test/Util/TestMemoryPool.c               |    2 +-
 core/Lucy/Test/Util/TestMemoryPool.cfh             |    2 +-
 core/Lucy/Test/Util/TestPriorityQueue.c            |    2 +-
 core/Lucy/Test/Util/TestPriorityQueue.cfh          |    2 +-
 161 files changed, 1273 insertions(+), 1273 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/c/t/test_lucy.c
----------------------------------------------------------------------
diff --git a/c/t/test_lucy.c b/c/t/test_lucy.c
index fc3f81e..808d0f7 100644
--- a/c/t/test_lucy.c
+++ b/c/t/test_lucy.c
@@ -16,7 +16,7 @@
 
 #include <stdlib.h>
 
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Clownfish/Test.h"
 #include "Lucy/Test.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test.c b/core/Clownfish/Test.c
index d569e55..4d2a9fc 100644
--- a/core/Clownfish/Test.c
+++ b/core/Clownfish/Test.c
@@ -23,9 +23,9 @@
 #include "Clownfish/Test.h"
 
 #include "Clownfish/Err.h"
-#include "Clownfish/Test/TestBatch.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/Test/TestRunner.h"
+#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestRunner.h"
 #include "Clownfish/VArray.h"
 
 #include "Clownfish/Test/TestByteBuf.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestBatch.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestBatch.c b/core/Clownfish/Test/TestBatch.c
deleted file mode 100644
index f77a71a..0000000
--- a/core/Clownfish/Test/TestBatch.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
-#define C_CFISH_TESTBATCH
-#define CFISH_USE_SHORT_NAMES
-#define LUCY_USE_SHORT_NAMES
-#include "Clownfish/Test/TestBatch.h"
-#include "Clownfish/CharBuf.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/VArray.h"
-#include "Clownfish/VTable.h"
-
-struct try_run_tests_context {
-    TestBatch *batch;
-};
-
-static void
-S_try_run_tests(void *context);
-
-static bool
-S_vtest_true(TestBatch *self, bool condition, const char *pattern,
-             va_list args);
-
-TestBatch*
-TestBatch_new(uint32_t num_planned, TestFormatter *formatter) {
-    TestBatch *self = (TestBatch*)VTable_Make_Obj(TESTBATCH);
-    return TestBatch_init(self, num_planned, formatter);
-}
-
-TestBatch*
-TestBatch_init(TestBatch *self, uint32_t num_planned,
-               TestFormatter *formatter) {
-    // Assign.
-    self->num_planned = num_planned;
-    self->formatter   = (TestFormatter*)INCREF(formatter);
-
-    // Initialize.
-    self->test_num    = 0;
-    self->num_passed  = 0;
-    self->num_failed  = 0;
-    self->num_skipped = 0;
-
-    return self;
-}
-
-void
-TestBatch_destroy(TestBatch *self) {
-    DECREF(self->formatter);
-    SUPER_DESTROY(self, TESTBATCH);
-}
-
-bool
-TestBatch_run(TestBatch *self) {
-    TestFormatter_Batch_Prologue(self->formatter, self);
-
-    struct try_run_tests_context args;
-    args.batch = self;
-    Err *err = Err_trap(S_try_run_tests, &args);
-
-    bool failed = false;
-    if (err) {
-        failed = true;
-        CharBuf *mess = Err_Get_Mess(err);
-        INCREF(mess);
-        Err_warn_mess(mess);
-    }
-    if (self->num_failed > 0) {
-        failed = true;
-        TestFormatter_batch_comment(self->formatter, "%d/%d tests failed.\n",
-                                    self->num_failed, self->test_num);
-    }
-    if (self->test_num != self->num_planned) {
-        failed = true;
-        TestFormatter_batch_comment(self->formatter,
-                                    "Bad plan: You planned %d tests but ran"
-                                    " %d.\n",
-                                    self->num_planned, self->test_num);
-    }
-
-    return !failed;
-}
-
-static void
-S_try_run_tests(void *context) {
-    struct try_run_tests_context *args
-        = (struct try_run_tests_context*)context;
-    TestBatch_Run_Tests(args->batch);
-}
-
-uint32_t
-TestBatch_get_num_planned(TestBatch *self) {
-    return self->num_planned;
-}
-
-uint32_t
-TestBatch_get_num_tests(TestBatch *self) {
-    return self->test_num;
-}
-
-uint32_t
-TestBatch_get_num_failed(TestBatch *self) {
-    return self->num_failed;
-}
-
-bool
-TestBatch_test_true(void *vself, bool condition, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_True((TestBatch*)vself, condition,
-                                         pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_test_false(void *vself, bool condition, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_False((TestBatch*)vself, condition,
-                                          pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_test_int_equals(void *vself, long got, long expected,
-                          const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_Int_Equals((TestBatch*)vself, got,
-                                               expected, pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_test_float_equals(void *vself, double got, double expected,
-                            const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_Float_Equals((TestBatch*)vself, got,
-                                                 expected, pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_test_string_equals(void *vself, const char *got,
-                             const char *expected, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VTest_String_Equals((TestBatch*)vself, got,
-                                                  expected, pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_pass(void *vself, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VPass((TestBatch*)vself, pattern, args);
-    va_end(args);
-    return result;
-}
-
-bool
-TestBatch_fail(void *vself, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    bool result = TestBatch_VFail((TestBatch*)vself, pattern, args);
-    va_end(args);
-    return result;
-}
-
-void
-TestBatch_skip(void *vself, const char *pattern, ...) {
-    va_list args;
-    va_start(args, pattern);
-    TestBatch_VSkip((TestBatch*)vself, pattern, args);
-    va_end(args);
-}
-
-bool
-TestBatch_vtest_true(TestBatch *self, bool condition, const char *pattern,
-                     va_list args) {
-    return S_vtest_true(self, condition, pattern, args);
-}
-
-bool
-TestBatch_vtest_false(TestBatch *self, bool condition,
-                      const char *pattern, va_list args) {
-    return S_vtest_true(self, !condition, pattern, args);
-}
-
-bool
-TestBatch_vtest_int_equals(TestBatch *self, long got, long expected,
-                           const char *pattern, va_list args) {
-    bool pass = (got == expected);
-    S_vtest_true(self, pass, pattern, args);
-    if (!pass) {
-        TestFormatter_test_comment(self->formatter,
-                                   "Expected '%ld', got '%ld'.\n",
-                                   expected, got);
-    }
-    return pass;
-}
-
-bool
-TestBatch_vtest_float_equals(TestBatch *self, double got, double expected,
-                             const char *pattern, va_list args) {
-    double relative_error = got / expected - 1.0;
-    bool   pass           = (fabs(relative_error) < 1e-6);
-    S_vtest_true(self, pass, pattern, args);
-    if (!pass) {
-        TestFormatter_test_comment(self->formatter,
-                                   "Expected '%e', got '%e'.\n",
-                                   expected, got);
-    }
-    return pass;
-}
-
-bool
-TestBatch_vtest_string_equals(TestBatch *self, const char *got,
-                              const char *expected, const char *pattern,
-                              va_list args) {
-    bool pass = (strcmp(got, expected) == 0);
-    S_vtest_true(self, pass, pattern, args);
-    if (!pass) {
-        TestFormatter_test_comment(self->formatter,
-                                   "Expected '%s', got '%s'.\n",
-                                   expected, got);
-    }
-    return pass;
-}
-
-bool
-TestBatch_vpass(TestBatch *self, const char *pattern, va_list args) {
-    return S_vtest_true(self, true, pattern, args);
-}
-
-bool
-TestBatch_vfail(TestBatch *self, const char *pattern, va_list args) {
-    return S_vtest_true(self, false, pattern, args);
-}
-
-void
-TestBatch_vskip(TestBatch *self, const char *pattern, va_list args) {
-    self->test_num++;
-    // TODO: Add a VTest_Skip method to TestFormatter
-    TestFormatter_VTest_Result(self->formatter, true, self->test_num,
-                               pattern, args);
-    self->num_skipped++;
-}
-
-static bool
-S_vtest_true(TestBatch* self, bool condition, const char *pattern,
-             va_list args) {
-    // Increment test number.
-    self->test_num++;
-
-    if (condition) {
-        self->num_passed++;
-    }
-    else {
-        self->num_failed++;
-    }
-
-    TestFormatter_VTest_Result(self->formatter, condition, self->test_num,
-                               pattern, args);
-
-    return condition;
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestBatch.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestBatch.cfh b/core/Clownfish/Test/TestBatch.cfh
deleted file mode 100644
index 01113a0..0000000
--- a/core/Clownfish/Test/TestBatch.cfh
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Clownfish;
-
-abstract class Clownfish::Test::TestBatch inherits Clownfish::Obj {
-    TestFormatter *formatter;
-    uint32_t       test_num;
-    uint32_t       num_planned;
-    uint32_t       num_passed;
-    uint32_t       num_failed;
-    uint32_t       num_skipped;
-
-    inert incremented TestBatch*
-    new(uint32_t num_planned, TestFormatter *formatter);
-
-    inert TestBatch*
-    init(TestBatch *self, uint32_t num_planned, TestFormatter *formatter);
-
-    public void
-    Destroy(TestBatch *self);
-
-    /** Run the test batch and print test output and diagnosis.
-     *
-     * @return true if the test batch passed.
-     */
-    bool
-    Run(TestBatch *self);
-
-    /** Run the tests of the test batch.
-     */
-    abstract void
-    Run_Tests(TestBatch *self);
-
-    /** Return the number of tests planned.
-     */
-    uint32_t
-    Get_Num_Planned(TestBatch *self);
-
-    /** Return the number of tests run.
-     */
-    uint32_t
-    Get_Num_Tests(TestBatch *self);
-
-    /** Return the number of failed tests.
-     */
-    uint32_t
-    Get_Num_Failed(TestBatch *self);
-
-    inert bool
-    test_true(void *vself, bool condition, const char *pattern, ...);
-
-    inert bool
-    test_false(void *vself, bool condition, const char *pattern, ...);
-
-    inert bool
-    test_int_equals(void *vself, long got, long expected,
-                    const char *pattern, ...);
-
-    inert bool
-    test_float_equals(void *vself, double got, double expected,
-                      const char *pattern, ...);
-
-    inert bool
-    test_string_equals(void *vself, const char *got, const char *expected,
-                       const char *pattern, ...);
-
-    inert bool
-    pass(void *vself, const char *pattern, ...);
-
-    inert bool
-    fail(void *vself, const char *pattern, ...);
-
-    inert void
-    skip(void *vself, const char *pattern, ...);
-
-    bool
-    VTest_True(TestBatch *self, bool condition, const char *pattern,
-               va_list args);
-
-    bool
-    VTest_False(TestBatch *self, bool condition, const char *pattern,
-                va_list args);
-
-    bool
-    VTest_Int_Equals(TestBatch *self, long got, long expected,
-                     const char *pattern, va_list args);
-
-    bool
-    VTest_Float_Equals(TestBatch *self, double got, double expected,
-                       const char *pattern, va_list args);
-
-    bool
-    VTest_String_Equals(TestBatch *self, const char *got, const char *expected,
-                       const char *pattern, va_list args);
-
-    bool
-    VPass(TestBatch *self, const char *pattern, va_list args);
-
-    bool
-    VFail(TestBatch *self, const char *pattern, va_list args);
-
-    void
-    VSkip(TestBatch *self, const char *pattern, va_list args);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestByteBuf.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestByteBuf.c b/core/Clownfish/Test/TestByteBuf.c
index 71329d7..98da9c3 100644
--- a/core/Clownfish/Test/TestByteBuf.c
+++ b/core/Clownfish/Test/TestByteBuf.c
@@ -23,8 +23,8 @@
 
 #include "Clownfish/ByteBuf.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VTable.h"
 
 TestByteBuf*

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestByteBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestByteBuf.cfh b/core/Clownfish/Test/TestByteBuf.cfh
index fba607b..6819191 100644
--- a/core/Clownfish/Test/TestByteBuf.cfh
+++ b/core/Clownfish/Test/TestByteBuf.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::TestByteBuf cnick TestBB
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestByteBuf*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestCharBuf.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestCharBuf.c b/core/Clownfish/Test/TestCharBuf.c
index 891731c..bc8a348 100644
--- a/core/Clownfish/Test/TestCharBuf.c
+++ b/core/Clownfish/Test/TestCharBuf.c
@@ -26,8 +26,8 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Num.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VTable.h"
 
 static char smiley[] = { (char)0xE2, (char)0x98, (char)0xBA, 0 };

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestCharBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestCharBuf.cfh b/core/Clownfish/Test/TestCharBuf.cfh
index 1ecedcc..ba27bdb 100644
--- a/core/Clownfish/Test/TestCharBuf.cfh
+++ b/core/Clownfish/Test/TestCharBuf.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::TestCharBuf cnick TestCB
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestCharBuf*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestErr.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestErr.c b/core/Clownfish/Test/TestErr.c
index c6b0869..7839de5 100644
--- a/core/Clownfish/Test/TestErr.c
+++ b/core/Clownfish/Test/TestErr.c
@@ -22,7 +22,7 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Clownfish/VTable.h"
 
 TestErr*

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestErr.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestErr.cfh b/core/Clownfish/Test/TestErr.cfh
index 1366e7e..4efd467 100644
--- a/core/Clownfish/Test/TestErr.cfh
+++ b/core/Clownfish/Test/TestErr.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::TestErr
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestErr*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestFormatter.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestFormatter.c b/core/Clownfish/Test/TestFormatter.c
deleted file mode 100644
index 5a700a2..0000000
--- a/core/Clownfish/Test/TestFormatter.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-
-#define C_CFISH_TESTFORMATTER
-#define CFISH_USE_SHORT_NAMES
-#define LUCY_USE_SHORT_NAMES
-#define CHY_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/CharBuf.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Test/TestBatch.h"
-#include "Clownfish/Test/TestRunner.h"
-#include "Clownfish/VTable.h"
-
-TestFormatter*
-TestFormatter_init(TestFormatter *self) {
-    ABSTRACT_CLASS_CHECK(self, TESTFORMATTER);
-    return self;
-}
-
-void
-TestFormatter_test_result(void *vself, bool pass, uint32_t test_num,
-                          const char *fmt, ...) {
-    va_list args;
-    va_start(args, fmt);
-    TestFormatter_VTest_Result((TestFormatter*)vself, pass, test_num, fmt,
-                               args);
-    va_end(args);
-}
-
-void
-TestFormatter_test_comment(void *vself, const char *fmt, ...) {
-    va_list args;
-    va_start(args, fmt);
-    TestFormatter_VTest_Comment((TestFormatter*)vself, fmt, args);
-    va_end(args);
-}
-
-void
-TestFormatter_batch_comment(void *vself, const char *fmt, ...) {
-    va_list args;
-    va_start(args, fmt);
-    TestFormatter_VBatch_Comment((TestFormatter*)vself, fmt, args);
-    va_end(args);
-}
-
-TestFormatterCF*
-TestFormatterCF_new() {
-    TestFormatterCF *self
-        = (TestFormatterCF*)VTable_Make_Obj(TESTFORMATTERCF);
-    return TestFormatterCF_init(self);
-}
-
-TestFormatterCF*
-TestFormatterCF_init(TestFormatterCF *self) {
-    return (TestFormatterCF*)TestFormatter_init((TestFormatter*)self);
-}
-
-void
-TestFormatterCF_batch_prologue(TestFormatterCF *self, TestBatch *batch) {
-    UNUSED_VAR(self);
-    CharBuf *class_name = TestBatch_Get_Class_Name(batch);
-    printf("Running %s...\n", CB_Get_Ptr8(class_name));
-}
-
-void
-TestFormatterCF_vtest_result(TestFormatterCF *self, bool pass,
-                             uint32_t test_num, const char *fmt,
-                             va_list args) {
-    UNUSED_VAR(self);
-    if (!pass) {
-        printf("  Failed test %u: ", test_num);
-        vprintf(fmt, args);
-        printf("\n");
-    }
-}
-
-void
-TestFormatterCF_vtest_comment(TestFormatterCF *self, const char *fmt,
-                              va_list args) {
-    UNUSED_VAR(self);
-    printf("    ");
-    vprintf(fmt, args);
-}
-
-void
-TestFormatterCF_vbatch_comment(TestFormatterCF *self, const char *fmt,
-                               va_list args) {
-    UNUSED_VAR(self);
-    printf("  ");
-    vprintf(fmt, args);
-}
-
-void
-TestFormatterCF_summary(TestFormatterCF *self, TestRunner *runner) {
-    UNUSED_VAR(self);
-    uint32_t num_batches        = TestRunner_Get_Num_Batches(runner);
-    uint32_t num_batches_failed = TestRunner_Get_Num_Batches_Failed(runner);
-    uint32_t num_tests          = TestRunner_Get_Num_Tests(runner);
-    uint32_t num_tests_failed   = TestRunner_Get_Num_Tests_Failed(runner);
-
-    if (num_batches == 0) {
-        printf("No tests planned or run.\n");
-    }
-    else if (num_batches_failed == 0) {
-        printf("%u batches passed. %u tests passed.\n", num_batches,
-               num_tests);
-        printf("Result: PASS\n");
-    }
-    else {
-        printf("%u/%u batches failed. %u/%u tests failed.\n",
-               num_batches_failed, num_batches, num_tests_failed, num_tests);
-        printf("Result: FAIL\n");
-    }
-}
-
-TestFormatterTAP*
-TestFormatterTAP_new() {
-    TestFormatterTAP *self
-        = (TestFormatterTAP*)VTable_Make_Obj(TESTFORMATTERTAP);
-    return TestFormatterTAP_init(self);
-}
-
-TestFormatterTAP*
-TestFormatterTAP_init(TestFormatterTAP *self) {
-    return (TestFormatterTAP*)TestFormatter_init((TestFormatter*)self);
-}
-
-void
-TestFormatterTAP_batch_prologue(TestFormatterTAP *self, TestBatch *batch) {
-    UNUSED_VAR(self);
-    printf("1..%u\n", TestBatch_Get_Num_Planned(batch));
-}
-
-void
-TestFormatterTAP_vtest_result(TestFormatterTAP *self, bool pass,
-                              uint32_t test_num, const char *fmt,
-                              va_list args) {
-    UNUSED_VAR(self);
-    const char *result = pass ? "ok" : "not ok";
-    printf("%s %u - ", result, test_num);
-    vprintf(fmt, args);
-    printf("\n");
-}
-
-void
-TestFormatterTAP_vtest_comment(TestFormatterTAP *self, const char *fmt,
-                               va_list args) {
-    UNUSED_VAR(self);
-    printf("#   ");
-    vprintf(fmt, args);
-}
-
-void
-TestFormatterTAP_vbatch_comment(TestFormatterTAP *self, const char *fmt,
-                                va_list args) {
-    UNUSED_VAR(self);
-    printf("# ");
-    vprintf(fmt, args);
-}
-
-void
-TestFormatterTAP_summary(TestFormatterTAP *self, TestRunner *runner) {
-    UNUSED_VAR(self);
-    UNUSED_VAR(runner);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestFormatter.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestFormatter.cfh b/core/Clownfish/Test/TestFormatter.cfh
deleted file mode 100644
index 2ba63bf..0000000
--- a/core/Clownfish/Test/TestFormatter.cfh
+++ /dev/null
@@ -1,138 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Clownfish;
-
-/**
- * Abstract base class for Clownfish test formatters.
- */
-abstract class Clownfish::Test::TestFormatter inherits Clownfish::Obj {
-    inert TestFormatter*
-    init(TestFormatter *self);
-
-    inert void
-    test_result(void *vself, bool pass, uint32_t test_num, const char *fmt,
-                ...);
-
-    inert void
-    test_comment(void *vself, const char *fmt, ...);
-
-    inert void
-    batch_comment(void *vself, const char *fmt, ...);
-
-    /** Print output at the beginning of a test batch.
-     *
-     * @param batch The test batch.
-     */
-    abstract void
-    Batch_Prologue(TestFormatter *self, TestBatch *batch);
-
-    /** Print the result of a single test.
-     *
-     * @param pass True if the test passed, false otherwise.
-     * @param test_num The sequence number of the test.
-     * @param fmt printf-style format string.
-     * @param args Additional arguments.
-     */
-    abstract void
-    VTest_Result(TestFormatter *self, bool pass, uint32_t test_num,
-                 const char *fmt, va_list args);
-
-    /** Print additional diagnosis for a test.
-     *
-     * @param fmt printf-style format string.
-     * @param args Additional arguments.
-     */
-    abstract void
-    VTest_Comment(TestFormatter *self, const char *fmt, va_list args);
-
-    /** Print additional diagnosis for a test batch.
-     *
-     * @param fmt printf-style format string.
-     * @param args Additional arguments.
-     */
-    abstract void
-    VBatch_Comment(TestFormatter *self, const char *fmt, va_list args);
-
-    /** Print test summary after running all test batches.
-     *
-     * @param runner The test runner.
-     */
-    abstract void
-    Summary(TestFormatter *self, TestRunner *runner);
-}
-
-/**
- * A TestFormatter that produces human-readable output in a custom
- * "Clownfish" format.
- */
-class Clownfish::Test::Formatter::TestFormatterCF
-    inherits Clownfish::Test::TestFormatter {
-
-    inert incremented TestFormatterCF*
-    new();
-
-    inert TestFormatterCF*
-    init(TestFormatterCF *self);
-
-    void
-    Batch_Prologue(TestFormatterCF *self, TestBatch *batch);
-
-    void
-    VTest_Result(TestFormatterCF *self, bool pass, uint32_t test_num,
-                 const char *fmt, va_list args);
-
-    void
-    VTest_Comment(TestFormatterCF *self, const char *fmt, va_list args);
-
-    void
-    VBatch_Comment(TestFormatterCF *self, const char *fmt, va_list args);
-
-    void
-    Summary(TestFormatterCF *self, TestRunner *runner);
-}
-
-/**
- * A TestFormatter that produces TAP output (Test Anything Protocol).
- * See http://testanything.org/
- */
-class Clownfish::Test::Formatter::TestFormatterTAP
-    inherits Clownfish::Test::TestFormatter {
-
-    inert incremented TestFormatterTAP*
-    new();
-
-    inert TestFormatterTAP*
-    init(TestFormatterTAP *self);
-
-    void
-    Batch_Prologue(TestFormatterTAP *self, TestBatch *batch);
-
-    void
-    VTest_Result(TestFormatterTAP *self, bool pass, uint32_t test_num,
-                 const char *fmt, va_list args);
-
-    void
-    VTest_Comment(TestFormatterTAP *self, const char *fmt, va_list args);
-
-    void
-    VBatch_Comment(TestFormatterTAP *self, const char *fmt, va_list args);
-
-    void
-    Summary(TestFormatterTAP *self, TestRunner *runner);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestHash.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestHash.c b/core/Clownfish/Test/TestHash.c
index 773a6f8..6b72ec7 100644
--- a/core/Clownfish/Test/TestHash.c
+++ b/core/Clownfish/Test/TestHash.c
@@ -26,8 +26,8 @@
 #include "Clownfish/Hash.h"
 #include "Clownfish/Num.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VArray.h"
 #include "Clownfish/VTable.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestHash.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestHash.cfh b/core/Clownfish/Test/TestHash.cfh
index ed5e548..cc74687 100644
--- a/core/Clownfish/Test/TestHash.cfh
+++ b/core/Clownfish/Test/TestHash.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::TestHash
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestHash*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestLockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestLockFreeRegistry.c b/core/Clownfish/Test/TestLockFreeRegistry.c
index 035bd77..dcd5e8b 100644
--- a/core/Clownfish/Test/TestLockFreeRegistry.c
+++ b/core/Clownfish/Test/TestLockFreeRegistry.c
@@ -24,7 +24,7 @@
 
 #include "Clownfish/LockFreeRegistry.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Clownfish/VTable.h"
 
 TestLockFreeRegistry*

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestLockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestLockFreeRegistry.cfh b/core/Clownfish/Test/TestLockFreeRegistry.cfh
index b2c7d36..376fbe2 100644
--- a/core/Clownfish/Test/TestLockFreeRegistry.cfh
+++ b/core/Clownfish/Test/TestLockFreeRegistry.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::TestLockFreeRegistry cnick TestLFReg
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestLockFreeRegistry*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestNum.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestNum.c b/core/Clownfish/Test/TestNum.c
index 1f01a61..add9a65 100644
--- a/core/Clownfish/Test/TestNum.c
+++ b/core/Clownfish/Test/TestNum.c
@@ -22,8 +22,8 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Num.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VTable.h"
 
 TestNum*

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestNum.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestNum.cfh b/core/Clownfish/Test/TestNum.cfh
index b6d1035..9176210 100644
--- a/core/Clownfish/Test/TestNum.cfh
+++ b/core/Clownfish/Test/TestNum.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::TestNum
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNum*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestObj.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestObj.c b/core/Clownfish/Test/TestObj.c
index fa0a80b..63d81f7 100644
--- a/core/Clownfish/Test/TestObj.c
+++ b/core/Clownfish/Test/TestObj.c
@@ -25,7 +25,7 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Clownfish/VTable.h"
 
 TestObj*

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestObj.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestObj.cfh b/core/Clownfish/Test/TestObj.cfh
index 3c41f2b..3cca164 100644
--- a/core/Clownfish/Test/TestObj.cfh
+++ b/core/Clownfish/Test/TestObj.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::TestObj
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestObj*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestRunner.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestRunner.c b/core/Clownfish/Test/TestRunner.c
deleted file mode 100644
index 8091c36..0000000
--- a/core/Clownfish/Test/TestRunner.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_CFISH_TESTRUNNER
-#define CFISH_USE_SHORT_NAMES
-#define LUCY_USE_SHORT_NAMES
-#define CHY_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestRunner.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Test/TestBatch.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/VTable.h"
-
-TestRunner*
-TestRunner_new(TestFormatter *formatter) {
-    TestRunner *self = (TestRunner*)VTable_Make_Obj(TESTRUNNER);
-    return TestRunner_init(self, formatter);
-}
-
-TestRunner*
-TestRunner_init(TestRunner *self, TestFormatter *formatter) {
-    self->formatter          = (TestFormatter*)INCREF(formatter);
-    self->num_tests          = 0;
-    self->num_tests_failed   = 0;
-    self->num_batches        = 0;
-    self->num_batches_failed = 0;
-
-    return self;
-}
-
-void
-TestRunner_destroy(TestRunner *self) {
-    DECREF(self->formatter);
-    SUPER_DESTROY(self, TESTRUNNER);
-}
-
-bool
-TestRunner_run_batch(TestRunner *self, TestBatch *batch) {
-    bool success = TestBatch_Run(batch);
-
-    self->num_tests        += TestBatch_Get_Num_Tests(batch);
-    self->num_tests_failed += TestBatch_Get_Num_Failed(batch);
-    self->num_batches      += 1;
-
-    if (!success) {
-        self->num_batches_failed += 1;
-    }
-
-    return success;
-}
-
-bool
-TestRunner_finish(TestRunner *self) {
-    TestFormatter_Summary(self->formatter, self);
-
-    return self->num_batches != 0 && self->num_batches_failed == 0;
-}
-
-uint32_t
-TestRunner_get_num_tests(TestRunner *self) {
-    return self->num_tests;
-}
-
-uint32_t
-TestRunner_get_num_tests_failed(TestRunner *self) {
-    return self->num_tests_failed;
-}
-
-uint32_t
-TestRunner_get_num_batches(TestRunner *self) {
-    return self->num_batches;
-}
-
-uint32_t
-TestRunner_get_num_batches_failed(TestRunner *self) {
-    return self->num_batches_failed;
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestRunner.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestRunner.cfh b/core/Clownfish/Test/TestRunner.cfh
deleted file mode 100644
index a59010a..0000000
--- a/core/Clownfish/Test/TestRunner.cfh
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Clownfish;
-
-/**
- * Run multiple test batches and collect statistics.
- */
-class Clownfish::Test::TestRunner inherits Clownfish::Obj {
-    TestFormatter *formatter;
-    uint32_t       num_tests;
-    uint32_t       num_tests_failed;
-    uint32_t       num_batches;
-    uint32_t       num_batches_failed;
-
-    inert incremented TestRunner*
-    new(TestFormatter *formatter);
-
-    /**
-     * @param formatter The test formatter to format the test output.
-     */
-    inert TestRunner*
-    init(TestRunner *self, TestFormatter *formatter);
-
-    public void
-    Destroy(TestRunner *self);
-
-    /** Run a test batch and collect statistics.
-     *
-     * @param batch The test batch.
-     * @return true if the test batch passed.
-     */
-    bool
-    Run_Batch(TestRunner *self, TestBatch *batch);
-
-    /** Print a summary after running all test batches.
-     *
-     * @return true if any tests were run and all test batches passed.
-     */
-    bool
-    Finish(TestRunner *self);
-
-    /** Return the number of tests run.
-     */
-    uint32_t
-    Get_Num_Tests(TestRunner *self);
-
-    /** Return the number of failed tests.
-     */
-    uint32_t
-    Get_Num_Tests_Failed(TestRunner *self);
-
-    /** Return the number of test batches run.
-     */
-    uint32_t
-    Get_Num_Batches(TestRunner *self);
-
-    /** Return the number of failed test batches.
-     */
-    uint32_t
-    Get_Num_Batches_Failed(TestRunner *self);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestUtils.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestUtils.c b/core/Clownfish/Test/TestUtils.c
deleted file mode 100644
index 0f7b72a..0000000
--- a/core/Clownfish/Test/TestUtils.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#define CHY_USE_SHORT_NAMES
-#define CFISH_USE_SHORT_NAMES
-#define LUCY_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestUtils.h"
-
-#include "Clownfish/CharBuf.h"
-#include "Clownfish/Util/Memory.h"
-#include "Lucy/Store/InStream.h"
-#include "Lucy/Store/OutStream.h"
-#include "Lucy/Store/RAMFile.h"
-#include "Lucy/Util/Freezer.h"
-
-uint64_t
-TestUtils_random_u64() {
-    uint64_t num = ((uint64_t)(rand()   & 0x7FFF) << 60)
-                   | ((uint64_t)(rand() & 0x7FFF) << 45)
-                   | ((uint64_t)(rand() & 0x7FFF) << 30)
-                   | ((uint64_t)(rand() & 0x7FFF) << 15)
-                   | ((uint64_t)(rand() & 0x7FFF) << 0);
-    return num;
-}
-
-int64_t*
-TestUtils_random_i64s(int64_t *buf, size_t count, int64_t min,
-                      int64_t limit) {
-    uint64_t  range = min < limit ? limit - min : 0;
-    int64_t *ints = buf ? buf : (int64_t*)CALLOCATE(count, sizeof(int64_t));
-    for (size_t i = 0; i < count; i++) {
-        ints[i] = min + TestUtils_random_u64() % range;
-    }
-    return ints;
-}
-
-uint64_t*
-TestUtils_random_u64s(uint64_t *buf, size_t count, uint64_t min,
-                      uint64_t limit) {
-    uint64_t  range = min < limit ? limit - min : 0;
-    uint64_t *ints = buf ? buf : (uint64_t*)CALLOCATE(count, sizeof(uint64_t));
-    for (size_t i = 0; i < count; i++) {
-        ints[i] = min + TestUtils_random_u64() % range;
-    }
-    return ints;
-}
-
-double*
-TestUtils_random_f64s(double *buf, size_t count) {
-    double *f64s = buf ? buf : (double*)CALLOCATE(count, sizeof(double));
-    for (size_t i = 0; i < count; i++) {
-        uint64_t num = TestUtils_random_u64();
-        f64s[i] = U64_TO_DOUBLE(num) / UINT64_MAX;
-    }
-    return f64s;
-}
-
-static uint32_t
-S_random_code_point(void) {
-    uint32_t code_point = 0;
-    while (1) {
-        uint8_t chance = (rand() % 9) + 1;
-        switch (chance) {
-            case 1: case 2: case 3:
-                code_point = rand() % 0x80;
-                break;
-            case 4: case 5: case 6:
-                code_point = (rand() % (0x0800  - 0x0080)) + 0x0080;
-                break;
-            case 7: case 8:
-                code_point = (rand() % (0x10000 - 0x0800)) + 0x0800;
-                break;
-            case 9: {
-                    uint64_t num = TestUtils_random_u64();
-                    code_point = (num % (0x10FFFF - 0x10000)) + 0x10000;
-                }
-        }
-        if (code_point > 0x10FFFF) {
-            continue; // Too high.
-        }
-        if (code_point > 0xD7FF && code_point < 0xE000) {
-            continue; // UTF-16 surrogate.
-        }
-        break;
-    }
-    return code_point;
-}
-
-CharBuf*
-TestUtils_random_string(size_t length) {
-    CharBuf *string = CB_new(length);
-    while (length--) {
-        CB_Cat_Char(string, S_random_code_point());
-    }
-    return string;
-}
-
-CharBuf*
-TestUtils_get_cb(const char *ptr) {
-    return CB_new_from_utf8(ptr, strlen(ptr));
-}
-
-Obj*
-TestUtils_freeze_thaw(Obj *object) {
-    if (object) {
-        RAMFile *ram_file = RAMFile_new(NULL, false);
-        OutStream *outstream = OutStream_open((Obj*)ram_file);
-        FREEZE(object, outstream);
-        OutStream_Close(outstream);
-        DECREF(outstream);
-
-        InStream *instream = InStream_open((Obj*)ram_file);
-        Obj *retval = THAW(instream);
-        DECREF(instream);
-        DECREF(ram_file);
-        return retval;
-    }
-    else {
-        return NULL;
-    }
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestUtils.cfh b/core/Clownfish/Test/TestUtils.cfh
deleted file mode 100644
index 5c88ec4..0000000
--- a/core/Clownfish/Test/TestUtils.cfh
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-parcel Clownfish;
-
-inert class Clownfish::Test::TestUtils  {
-
-    /** Testing-only CharBuf factory which uses strlen().
-     */
-    inert incremented CharBuf*
-    get_cb(const char *utf8);
-
-    /** Return a random unsigned 64-bit integer.
-     */
-    inert uint64_t
-    random_u64();
-
-    /** Return an array of <code>count</code> random 64-bit integers where
-     * <code>min <= n < limit</code>.
-     *
-     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
-     * be used.
-     */
-    inert int64_t*
-    random_i64s(int64_t *buf, size_t count, int64_t min, int64_t limit);
-
-    /** Return an array of <code>count</code> random unsigned, 64-bit integers
-     * where <code>min <= n < limit</code>.
-     *
-     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
-     * be used.
-     */
-    inert uint64_t*
-    random_u64s(uint64_t *buf, size_t count, uint64_t min, uint64_t limit);
-
-    /** Return an array of <code>count</code> random double-precision floating
-     * point numbers between 0 and 1.
-     *
-     * If <code>buf</code> is NULL, it will be allocated, otherwise it will
-     * be used.
-     */
-    inert double*
-    random_f64s(double *buf, size_t count);
-
-    /** Return a string with a random (legal) sequence of code points.
-     * @param length Length of the string in code points.
-     */
-    inert incremented CharBuf*
-    random_string(size_t length);
-
-    /** Return the result of round-tripping the object through FREEZE and
-     * THAW.
-     */
-    inert incremented Obj*
-    freeze_thaw(Obj *object);
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestVArray.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestVArray.c b/core/Clownfish/Test/TestVArray.c
index 99b5918..110c01b 100644
--- a/core/Clownfish/Test/TestVArray.c
+++ b/core/Clownfish/Test/TestVArray.c
@@ -25,8 +25,8 @@
 #include "Clownfish/Err.h"
 #include "Clownfish/Num.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VArray.h"
 #include "Clownfish/VTable.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/TestVArray.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestVArray.cfh b/core/Clownfish/Test/TestVArray.cfh
index 481dbb4..478127a 100644
--- a/core/Clownfish/Test/TestVArray.cfh
+++ b/core/Clownfish/Test/TestVArray.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::TestVArray
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestVArray*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/Util/TestAtomic.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestAtomic.c b/core/Clownfish/Test/Util/TestAtomic.c
index 3610f7d..6187198 100644
--- a/core/Clownfish/Test/Util/TestAtomic.c
+++ b/core/Clownfish/Test/Util/TestAtomic.c
@@ -20,7 +20,7 @@
 #include "Clownfish/Test/Util/TestAtomic.h"
 
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Clownfish/Util/Atomic.h"
 #include "Clownfish/VTable.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/Util/TestAtomic.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestAtomic.cfh b/core/Clownfish/Test/Util/TestAtomic.cfh
index 90d905e..576eec9 100644
--- a/core/Clownfish/Test/Util/TestAtomic.cfh
+++ b/core/Clownfish/Test/Util/TestAtomic.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::Util::TestAtomic
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestAtomic*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/Util/TestMemory.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestMemory.c b/core/Clownfish/Test/Util/TestMemory.c
index a3ac538..0c58b99 100644
--- a/core/Clownfish/Test/Util/TestMemory.c
+++ b/core/Clownfish/Test/Util/TestMemory.c
@@ -21,7 +21,7 @@
 #include "Clownfish/Test/Util/TestMemory.h"
 
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/VTable.h"
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/Util/TestMemory.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestMemory.cfh b/core/Clownfish/Test/Util/TestMemory.cfh
index 23252c2..6426935 100644
--- a/core/Clownfish/Test/Util/TestMemory.cfh
+++ b/core/Clownfish/Test/Util/TestMemory.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::Util::TestMemory
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestMemory*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/Util/TestNumberUtils.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestNumberUtils.c b/core/Clownfish/Test/Util/TestNumberUtils.c
index b524818..04c79f0 100644
--- a/core/Clownfish/Test/Util/TestNumberUtils.c
+++ b/core/Clownfish/Test/Util/TestNumberUtils.c
@@ -24,8 +24,8 @@
 
 #include "Clownfish/Err.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/Util/NumberUtils.h"
 #include "Clownfish/VTable.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/Util/TestNumberUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestNumberUtils.cfh b/core/Clownfish/Test/Util/TestNumberUtils.cfh
index 1c6659e..1e4bacc 100644
--- a/core/Clownfish/Test/Util/TestNumberUtils.cfh
+++ b/core/Clownfish/Test/Util/TestNumberUtils.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::Util::TestNumberUtils cnick TestNumUtil
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNumberUtils*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/Util/TestStringHelper.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestStringHelper.c b/core/Clownfish/Test/Util/TestStringHelper.c
index 18cc4db..0ca46e9 100644
--- a/core/Clownfish/Test/Util/TestStringHelper.c
+++ b/core/Clownfish/Test/Util/TestStringHelper.c
@@ -24,8 +24,8 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/Test/TestFormatter.h"
-#include "Clownfish/Test/TestUtils.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/Util/StringHelper.h"
 #include "Clownfish/VTable.h"
 #include "Lucy/Util/Json.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/Test/Util/TestStringHelper.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/Util/TestStringHelper.cfh b/core/Clownfish/Test/Util/TestStringHelper.cfh
index 1c33ea5..219ec81 100644
--- a/core/Clownfish/Test/Util/TestStringHelper.cfh
+++ b/core/Clownfish/Test/Util/TestStringHelper.cfh
@@ -17,7 +17,7 @@
 parcel TestClownfish;
 
 class Clownfish::Test::Util::TestStringHelper cnick TestStrHelp
-    inherits Clownfish::Test::TestBatch {
+    inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestStringHelper*
     new(TestFormatter *formatter);

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/TestHarness/TestBatch.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestBatch.c b/core/Clownfish/TestHarness/TestBatch.c
new file mode 100644
index 0000000..486e967
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestBatch.c
@@ -0,0 +1,293 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#define C_CFISH_TESTBATCH
+#define CFISH_USE_SHORT_NAMES
+#define LUCY_USE_SHORT_NAMES
+#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/VArray.h"
+#include "Clownfish/VTable.h"
+
+struct try_run_tests_context {
+    TestBatch *batch;
+};
+
+static void
+S_try_run_tests(void *context);
+
+static bool
+S_vtest_true(TestBatch *self, bool condition, const char *pattern,
+             va_list args);
+
+TestBatch*
+TestBatch_new(uint32_t num_planned, TestFormatter *formatter) {
+    TestBatch *self = (TestBatch*)VTable_Make_Obj(TESTBATCH);
+    return TestBatch_init(self, num_planned, formatter);
+}
+
+TestBatch*
+TestBatch_init(TestBatch *self, uint32_t num_planned,
+               TestFormatter *formatter) {
+    // Assign.
+    self->num_planned = num_planned;
+    self->formatter   = (TestFormatter*)INCREF(formatter);
+
+    // Initialize.
+    self->test_num    = 0;
+    self->num_passed  = 0;
+    self->num_failed  = 0;
+    self->num_skipped = 0;
+
+    return self;
+}
+
+void
+TestBatch_destroy(TestBatch *self) {
+    DECREF(self->formatter);
+    SUPER_DESTROY(self, TESTBATCH);
+}
+
+bool
+TestBatch_run(TestBatch *self) {
+    TestFormatter_Batch_Prologue(self->formatter, self);
+
+    struct try_run_tests_context args;
+    args.batch = self;
+    Err *err = Err_trap(S_try_run_tests, &args);
+
+    bool failed = false;
+    if (err) {
+        failed = true;
+        CharBuf *mess = Err_Get_Mess(err);
+        INCREF(mess);
+        Err_warn_mess(mess);
+    }
+    if (self->num_failed > 0) {
+        failed = true;
+        TestFormatter_batch_comment(self->formatter, "%d/%d tests failed.\n",
+                                    self->num_failed, self->test_num);
+    }
+    if (self->test_num != self->num_planned) {
+        failed = true;
+        TestFormatter_batch_comment(self->formatter,
+                                    "Bad plan: You planned %d tests but ran"
+                                    " %d.\n",
+                                    self->num_planned, self->test_num);
+    }
+
+    return !failed;
+}
+
+static void
+S_try_run_tests(void *context) {
+    struct try_run_tests_context *args
+        = (struct try_run_tests_context*)context;
+    TestBatch_Run_Tests(args->batch);
+}
+
+uint32_t
+TestBatch_get_num_planned(TestBatch *self) {
+    return self->num_planned;
+}
+
+uint32_t
+TestBatch_get_num_tests(TestBatch *self) {
+    return self->test_num;
+}
+
+uint32_t
+TestBatch_get_num_failed(TestBatch *self) {
+    return self->num_failed;
+}
+
+bool
+TestBatch_test_true(void *vself, bool condition, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatch_VTest_True((TestBatch*)vself, condition,
+                                         pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatch_test_false(void *vself, bool condition, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatch_VTest_False((TestBatch*)vself, condition,
+                                          pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatch_test_int_equals(void *vself, long got, long expected,
+                          const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatch_VTest_Int_Equals((TestBatch*)vself, got,
+                                               expected, pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatch_test_float_equals(void *vself, double got, double expected,
+                            const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatch_VTest_Float_Equals((TestBatch*)vself, got,
+                                                 expected, pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatch_test_string_equals(void *vself, const char *got,
+                             const char *expected, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatch_VTest_String_Equals((TestBatch*)vself, got,
+                                                  expected, pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatch_pass(void *vself, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatch_VPass((TestBatch*)vself, pattern, args);
+    va_end(args);
+    return result;
+}
+
+bool
+TestBatch_fail(void *vself, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    bool result = TestBatch_VFail((TestBatch*)vself, pattern, args);
+    va_end(args);
+    return result;
+}
+
+void
+TestBatch_skip(void *vself, const char *pattern, ...) {
+    va_list args;
+    va_start(args, pattern);
+    TestBatch_VSkip((TestBatch*)vself, pattern, args);
+    va_end(args);
+}
+
+bool
+TestBatch_vtest_true(TestBatch *self, bool condition, const char *pattern,
+                     va_list args) {
+    return S_vtest_true(self, condition, pattern, args);
+}
+
+bool
+TestBatch_vtest_false(TestBatch *self, bool condition,
+                      const char *pattern, va_list args) {
+    return S_vtest_true(self, !condition, pattern, args);
+}
+
+bool
+TestBatch_vtest_int_equals(TestBatch *self, long got, long expected,
+                           const char *pattern, va_list args) {
+    bool pass = (got == expected);
+    S_vtest_true(self, pass, pattern, args);
+    if (!pass) {
+        TestFormatter_test_comment(self->formatter,
+                                   "Expected '%ld', got '%ld'.\n",
+                                   expected, got);
+    }
+    return pass;
+}
+
+bool
+TestBatch_vtest_float_equals(TestBatch *self, double got, double expected,
+                             const char *pattern, va_list args) {
+    double relative_error = got / expected - 1.0;
+    bool   pass           = (fabs(relative_error) < 1e-6);
+    S_vtest_true(self, pass, pattern, args);
+    if (!pass) {
+        TestFormatter_test_comment(self->formatter,
+                                   "Expected '%e', got '%e'.\n",
+                                   expected, got);
+    }
+    return pass;
+}
+
+bool
+TestBatch_vtest_string_equals(TestBatch *self, const char *got,
+                              const char *expected, const char *pattern,
+                              va_list args) {
+    bool pass = (strcmp(got, expected) == 0);
+    S_vtest_true(self, pass, pattern, args);
+    if (!pass) {
+        TestFormatter_test_comment(self->formatter,
+                                   "Expected '%s', got '%s'.\n",
+                                   expected, got);
+    }
+    return pass;
+}
+
+bool
+TestBatch_vpass(TestBatch *self, const char *pattern, va_list args) {
+    return S_vtest_true(self, true, pattern, args);
+}
+
+bool
+TestBatch_vfail(TestBatch *self, const char *pattern, va_list args) {
+    return S_vtest_true(self, false, pattern, args);
+}
+
+void
+TestBatch_vskip(TestBatch *self, const char *pattern, va_list args) {
+    self->test_num++;
+    // TODO: Add a VTest_Skip method to TestFormatter
+    TestFormatter_VTest_Result(self->formatter, true, self->test_num,
+                               pattern, args);
+    self->num_skipped++;
+}
+
+static bool
+S_vtest_true(TestBatch* self, bool condition, const char *pattern,
+             va_list args) {
+    // Increment test number.
+    self->test_num++;
+
+    if (condition) {
+        self->num_passed++;
+    }
+    else {
+        self->num_failed++;
+    }
+
+    TestFormatter_VTest_Result(self->formatter, condition, self->test_num,
+                               pattern, args);
+
+    return condition;
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/TestHarness/TestBatch.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestBatch.cfh b/core/Clownfish/TestHarness/TestBatch.cfh
new file mode 100644
index 0000000..cf82286
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestBatch.cfh
@@ -0,0 +1,120 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Clownfish;
+
+abstract class Clownfish::TestHarness::TestBatch inherits Clownfish::Obj {
+    TestFormatter *formatter;
+    uint32_t       test_num;
+    uint32_t       num_planned;
+    uint32_t       num_passed;
+    uint32_t       num_failed;
+    uint32_t       num_skipped;
+
+    inert incremented TestBatch*
+    new(uint32_t num_planned, TestFormatter *formatter);
+
+    inert TestBatch*
+    init(TestBatch *self, uint32_t num_planned, TestFormatter *formatter);
+
+    public void
+    Destroy(TestBatch *self);
+
+    /** Run the test batch and print test output and diagnosis.
+     *
+     * @return true if the test batch passed.
+     */
+    bool
+    Run(TestBatch *self);
+
+    /** Run the tests of the test batch.
+     */
+    abstract void
+    Run_Tests(TestBatch *self);
+
+    /** Return the number of tests planned.
+     */
+    uint32_t
+    Get_Num_Planned(TestBatch *self);
+
+    /** Return the number of tests run.
+     */
+    uint32_t
+    Get_Num_Tests(TestBatch *self);
+
+    /** Return the number of failed tests.
+     */
+    uint32_t
+    Get_Num_Failed(TestBatch *self);
+
+    inert bool
+    test_true(void *vself, bool condition, const char *pattern, ...);
+
+    inert bool
+    test_false(void *vself, bool condition, const char *pattern, ...);
+
+    inert bool
+    test_int_equals(void *vself, long got, long expected,
+                    const char *pattern, ...);
+
+    inert bool
+    test_float_equals(void *vself, double got, double expected,
+                      const char *pattern, ...);
+
+    inert bool
+    test_string_equals(void *vself, const char *got, const char *expected,
+                       const char *pattern, ...);
+
+    inert bool
+    pass(void *vself, const char *pattern, ...);
+
+    inert bool
+    fail(void *vself, const char *pattern, ...);
+
+    inert void
+    skip(void *vself, const char *pattern, ...);
+
+    bool
+    VTest_True(TestBatch *self, bool condition, const char *pattern,
+               va_list args);
+
+    bool
+    VTest_False(TestBatch *self, bool condition, const char *pattern,
+                va_list args);
+
+    bool
+    VTest_Int_Equals(TestBatch *self, long got, long expected,
+                     const char *pattern, va_list args);
+
+    bool
+    VTest_Float_Equals(TestBatch *self, double got, double expected,
+                       const char *pattern, va_list args);
+
+    bool
+    VTest_String_Equals(TestBatch *self, const char *got, const char *expected,
+                       const char *pattern, va_list args);
+
+    bool
+    VPass(TestBatch *self, const char *pattern, va_list args);
+
+    bool
+    VFail(TestBatch *self, const char *pattern, va_list args);
+
+    void
+    VSkip(TestBatch *self, const char *pattern, va_list args);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/TestHarness/TestFormatter.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestFormatter.c b/core/Clownfish/TestHarness/TestFormatter.c
new file mode 100644
index 0000000..b6f0ac0
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestFormatter.c
@@ -0,0 +1,184 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#define C_CFISH_TESTFORMATTER
+#define CFISH_USE_SHORT_NAMES
+#define LUCY_USE_SHORT_NAMES
+#define CHY_USE_SHORT_NAMES
+
+#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestRunner.h"
+#include "Clownfish/VTable.h"
+
+TestFormatter*
+TestFormatter_init(TestFormatter *self) {
+    ABSTRACT_CLASS_CHECK(self, TESTFORMATTER);
+    return self;
+}
+
+void
+TestFormatter_test_result(void *vself, bool pass, uint32_t test_num,
+                          const char *fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    TestFormatter_VTest_Result((TestFormatter*)vself, pass, test_num, fmt,
+                               args);
+    va_end(args);
+}
+
+void
+TestFormatter_test_comment(void *vself, const char *fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    TestFormatter_VTest_Comment((TestFormatter*)vself, fmt, args);
+    va_end(args);
+}
+
+void
+TestFormatter_batch_comment(void *vself, const char *fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    TestFormatter_VBatch_Comment((TestFormatter*)vself, fmt, args);
+    va_end(args);
+}
+
+TestFormatterCF*
+TestFormatterCF_new() {
+    TestFormatterCF *self
+        = (TestFormatterCF*)VTable_Make_Obj(TESTFORMATTERCF);
+    return TestFormatterCF_init(self);
+}
+
+TestFormatterCF*
+TestFormatterCF_init(TestFormatterCF *self) {
+    return (TestFormatterCF*)TestFormatter_init((TestFormatter*)self);
+}
+
+void
+TestFormatterCF_batch_prologue(TestFormatterCF *self, TestBatch *batch) {
+    UNUSED_VAR(self);
+    CharBuf *class_name = TestBatch_Get_Class_Name(batch);
+    printf("Running %s...\n", CB_Get_Ptr8(class_name));
+}
+
+void
+TestFormatterCF_vtest_result(TestFormatterCF *self, bool pass,
+                             uint32_t test_num, const char *fmt,
+                             va_list args) {
+    UNUSED_VAR(self);
+    if (!pass) {
+        printf("  Failed test %u: ", test_num);
+        vprintf(fmt, args);
+        printf("\n");
+    }
+}
+
+void
+TestFormatterCF_vtest_comment(TestFormatterCF *self, const char *fmt,
+                              va_list args) {
+    UNUSED_VAR(self);
+    printf("    ");
+    vprintf(fmt, args);
+}
+
+void
+TestFormatterCF_vbatch_comment(TestFormatterCF *self, const char *fmt,
+                               va_list args) {
+    UNUSED_VAR(self);
+    printf("  ");
+    vprintf(fmt, args);
+}
+
+void
+TestFormatterCF_summary(TestFormatterCF *self, TestRunner *runner) {
+    UNUSED_VAR(self);
+    uint32_t num_batches        = TestRunner_Get_Num_Batches(runner);
+    uint32_t num_batches_failed = TestRunner_Get_Num_Batches_Failed(runner);
+    uint32_t num_tests          = TestRunner_Get_Num_Tests(runner);
+    uint32_t num_tests_failed   = TestRunner_Get_Num_Tests_Failed(runner);
+
+    if (num_batches == 0) {
+        printf("No tests planned or run.\n");
+    }
+    else if (num_batches_failed == 0) {
+        printf("%u batches passed. %u tests passed.\n", num_batches,
+               num_tests);
+        printf("Result: PASS\n");
+    }
+    else {
+        printf("%u/%u batches failed. %u/%u tests failed.\n",
+               num_batches_failed, num_batches, num_tests_failed, num_tests);
+        printf("Result: FAIL\n");
+    }
+}
+
+TestFormatterTAP*
+TestFormatterTAP_new() {
+    TestFormatterTAP *self
+        = (TestFormatterTAP*)VTable_Make_Obj(TESTFORMATTERTAP);
+    return TestFormatterTAP_init(self);
+}
+
+TestFormatterTAP*
+TestFormatterTAP_init(TestFormatterTAP *self) {
+    return (TestFormatterTAP*)TestFormatter_init((TestFormatter*)self);
+}
+
+void
+TestFormatterTAP_batch_prologue(TestFormatterTAP *self, TestBatch *batch) {
+    UNUSED_VAR(self);
+    printf("1..%u\n", TestBatch_Get_Num_Planned(batch));
+}
+
+void
+TestFormatterTAP_vtest_result(TestFormatterTAP *self, bool pass,
+                              uint32_t test_num, const char *fmt,
+                              va_list args) {
+    UNUSED_VAR(self);
+    const char *result = pass ? "ok" : "not ok";
+    printf("%s %u - ", result, test_num);
+    vprintf(fmt, args);
+    printf("\n");
+}
+
+void
+TestFormatterTAP_vtest_comment(TestFormatterTAP *self, const char *fmt,
+                               va_list args) {
+    UNUSED_VAR(self);
+    printf("#   ");
+    vprintf(fmt, args);
+}
+
+void
+TestFormatterTAP_vbatch_comment(TestFormatterTAP *self, const char *fmt,
+                                va_list args) {
+    UNUSED_VAR(self);
+    printf("# ");
+    vprintf(fmt, args);
+}
+
+void
+TestFormatterTAP_summary(TestFormatterTAP *self, TestRunner *runner) {
+    UNUSED_VAR(self);
+    UNUSED_VAR(runner);
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/d4d7d029/core/Clownfish/TestHarness/TestFormatter.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/TestHarness/TestFormatter.cfh b/core/Clownfish/TestHarness/TestFormatter.cfh
new file mode 100644
index 0000000..06402d2
--- /dev/null
+++ b/core/Clownfish/TestHarness/TestFormatter.cfh
@@ -0,0 +1,138 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+parcel Clownfish;
+
+/**
+ * Abstract base class for Clownfish test formatters.
+ */
+abstract class Clownfish::TestHarness::TestFormatter inherits Clownfish::Obj {
+    inert TestFormatter*
+    init(TestFormatter *self);
+
+    inert void
+    test_result(void *vself, bool pass, uint32_t test_num, const char *fmt,
+                ...);
+
+    inert void
+    test_comment(void *vself, const char *fmt, ...);
+
+    inert void
+    batch_comment(void *vself, const char *fmt, ...);
+
+    /** Print output at the beginning of a test batch.
+     *
+     * @param batch The test batch.
+     */
+    abstract void
+    Batch_Prologue(TestFormatter *self, TestBatch *batch);
+
+    /** Print the result of a single test.
+     *
+     * @param pass True if the test passed, false otherwise.
+     * @param test_num The sequence number of the test.
+     * @param fmt printf-style format string.
+     * @param args Additional arguments.
+     */
+    abstract void
+    VTest_Result(TestFormatter *self, bool pass, uint32_t test_num,
+                 const char *fmt, va_list args);
+
+    /** Print additional diagnosis for a test.
+     *
+     * @param fmt printf-style format string.
+     * @param args Additional arguments.
+     */
+    abstract void
+    VTest_Comment(TestFormatter *self, const char *fmt, va_list args);
+
+    /** Print additional diagnosis for a test batch.
+     *
+     * @param fmt printf-style format string.
+     * @param args Additional arguments.
+     */
+    abstract void
+    VBatch_Comment(TestFormatter *self, const char *fmt, va_list args);
+
+    /** Print test summary after running all test batches.
+     *
+     * @param runner The test runner.
+     */
+    abstract void
+    Summary(TestFormatter *self, TestRunner *runner);
+}
+
+/**
+ * A TestFormatter that produces human-readable output in a custom
+ * "Clownfish" format.
+ */
+class Clownfish::Test::Formatter::TestFormatterCF
+    inherits Clownfish::TestHarness::TestFormatter {
+
+    inert incremented TestFormatterCF*
+    new();
+
+    inert TestFormatterCF*
+    init(TestFormatterCF *self);
+
+    void
+    Batch_Prologue(TestFormatterCF *self, TestBatch *batch);
+
+    void
+    VTest_Result(TestFormatterCF *self, bool pass, uint32_t test_num,
+                 const char *fmt, va_list args);
+
+    void
+    VTest_Comment(TestFormatterCF *self, const char *fmt, va_list args);
+
+    void
+    VBatch_Comment(TestFormatterCF *self, const char *fmt, va_list args);
+
+    void
+    Summary(TestFormatterCF *self, TestRunner *runner);
+}
+
+/**
+ * A TestFormatter that produces TAP output (Test Anything Protocol).
+ * See http://testanything.org/
+ */
+class Clownfish::Test::Formatter::TestFormatterTAP
+    inherits Clownfish::TestHarness::TestFormatter {
+
+    inert incremented TestFormatterTAP*
+    new();
+
+    inert TestFormatterTAP*
+    init(TestFormatterTAP *self);
+
+    void
+    Batch_Prologue(TestFormatterTAP *self, TestBatch *batch);
+
+    void
+    VTest_Result(TestFormatterTAP *self, bool pass, uint32_t test_num,
+                 const char *fmt, va_list args);
+
+    void
+    VTest_Comment(TestFormatterTAP *self, const char *fmt, va_list args);
+
+    void
+    VBatch_Comment(TestFormatterTAP *self, const char *fmt, va_list args);
+
+    void
+    Summary(TestFormatterTAP *self, TestRunner *runner);
+}
+
+


[lucy-commits] [19/26] git commit: refs/heads/separate-clownfish-wip2 - Move Lucy tests to a separate parcel TestLucy

Posted by nw...@apache.org.
Move Lucy tests to a separate parcel TestLucy


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/ffb0e921
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/ffb0e921
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/ffb0e921

Branch: refs/heads/separate-clownfish-wip2
Commit: ffb0e921389b2546ee70b89b802cba89a2a0b8f5
Parents: 9f826b3
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 27 20:48:40 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:32:00 2013 +0200

----------------------------------------------------------------------
 c/t/test_lucy.c                                    |    4 +-
 common/charmonizer.c                               |    9 ++++++
 common/charmonizer.main                            |    9 ++++++
 core/Lucy/Test.c                                   |    1 +
 core/Lucy/Test.cfh                                 |    2 +-
 core/Lucy/Test/Analysis/TestAnalyzer.c             |    1 +
 core/Lucy/Test/Analysis/TestAnalyzer.cfh           |    2 +-
 core/Lucy/Test/Analysis/TestCaseFolder.c           |    3 +-
 core/Lucy/Test/Analysis/TestCaseFolder.cfh         |    2 +-
 core/Lucy/Test/Analysis/TestNormalizer.c           |    3 +-
 core/Lucy/Test/Analysis/TestNormalizer.cfh         |    2 +-
 core/Lucy/Test/Analysis/TestPolyAnalyzer.c         |    3 +-
 core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh       |    2 +-
 core/Lucy/Test/Analysis/TestRegexTokenizer.c       |    3 +-
 core/Lucy/Test/Analysis/TestRegexTokenizer.cfh     |    2 +-
 core/Lucy/Test/Analysis/TestSnowballStemmer.c      |    3 +-
 core/Lucy/Test/Analysis/TestSnowballStemmer.cfh    |    2 +-
 core/Lucy/Test/Analysis/TestSnowballStopFilter.c   |    3 +-
 core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh |    2 +-
 core/Lucy/Test/Analysis/TestStandardTokenizer.c    |    3 +-
 core/Lucy/Test/Analysis/TestStandardTokenizer.cfh  |    2 +-
 core/Lucy/Test/Highlight/TestHeatMap.c             |    1 +
 core/Lucy/Test/Highlight/TestHeatMap.cfh           |    2 +-
 core/Lucy/Test/Highlight/TestHighlighter.c         |    3 +-
 core/Lucy/Test/Highlight/TestHighlighter.cfh       |    2 +-
 core/Lucy/Test/Index/TestDocWriter.c               |    3 +-
 core/Lucy/Test/Index/TestDocWriter.cfh             |    2 +-
 core/Lucy/Test/Index/TestHighlightWriter.c         |    3 +-
 core/Lucy/Test/Index/TestHighlightWriter.cfh       |    2 +-
 core/Lucy/Test/Index/TestIndexManager.c            |    1 +
 core/Lucy/Test/Index/TestIndexManager.cfh          |    2 +-
 core/Lucy/Test/Index/TestPolyReader.c              |    3 +-
 core/Lucy/Test/Index/TestPolyReader.cfh            |    2 +-
 core/Lucy/Test/Index/TestPostingListWriter.c       |    3 +-
 core/Lucy/Test/Index/TestPostingListWriter.cfh     |    2 +-
 core/Lucy/Test/Index/TestSegWriter.c               |    3 +-
 core/Lucy/Test/Index/TestSegWriter.cfh             |    2 +-
 core/Lucy/Test/Index/TestSegment.c                 |    3 +-
 core/Lucy/Test/Index/TestSegment.cfh               |    2 +-
 core/Lucy/Test/Index/TestSnapshot.c                |    1 +
 core/Lucy/Test/Index/TestSnapshot.cfh              |    2 +-
 core/Lucy/Test/Index/TestTermInfo.c                |    3 +-
 core/Lucy/Test/Index/TestTermInfo.cfh              |    2 +-
 core/Lucy/Test/Object/TestBitVector.c              |    3 +-
 core/Lucy/Test/Object/TestBitVector.cfh            |    2 +-
 core/Lucy/Test/Object/TestI32Array.c               |    3 +-
 core/Lucy/Test/Object/TestI32Array.cfh             |    2 +-
 core/Lucy/Test/Plan/TestArchitecture.c             |    3 +-
 core/Lucy/Test/Plan/TestArchitecture.cfh           |    2 +-
 core/Lucy/Test/Plan/TestBlobType.c                 |    3 +-
 core/Lucy/Test/Plan/TestBlobType.cfh               |    2 +-
 core/Lucy/Test/Plan/TestFieldMisc.c                |    1 +
 core/Lucy/Test/Plan/TestFieldMisc.cfh              |    2 +-
 core/Lucy/Test/Plan/TestFieldType.c                |    3 +-
 core/Lucy/Test/Plan/TestFieldType.cfh              |    2 +-
 core/Lucy/Test/Plan/TestFullTextType.c             |    3 +-
 core/Lucy/Test/Plan/TestFullTextType.cfh           |    2 +-
 core/Lucy/Test/Plan/TestNumericType.c              |    3 +-
 core/Lucy/Test/Plan/TestNumericType.cfh            |    2 +-
 core/Lucy/Test/Search/TestLeafQuery.c              |    3 +-
 core/Lucy/Test/Search/TestLeafQuery.cfh            |    2 +-
 core/Lucy/Test/Search/TestMatchAllQuery.c          |    3 +-
 core/Lucy/Test/Search/TestMatchAllQuery.cfh        |    2 +-
 core/Lucy/Test/Search/TestNOTQuery.c               |    3 +-
 core/Lucy/Test/Search/TestNOTQuery.cfh             |    2 +-
 core/Lucy/Test/Search/TestNoMatchQuery.c           |    3 +-
 core/Lucy/Test/Search/TestNoMatchQuery.cfh         |    2 +-
 core/Lucy/Test/Search/TestPhraseQuery.c            |    3 +-
 core/Lucy/Test/Search/TestPhraseQuery.cfh          |    2 +-
 core/Lucy/Test/Search/TestPolyQuery.c              |    3 +-
 core/Lucy/Test/Search/TestPolyQuery.cfh            |    2 +-
 core/Lucy/Test/Search/TestQueryParser.c            |    3 +-
 core/Lucy/Test/Search/TestQueryParser.cfh          |    2 +-
 core/Lucy/Test/Search/TestQueryParserLogic.c       |   11 ++++---
 core/Lucy/Test/Search/TestQueryParserLogic.cfh     |    2 +-
 core/Lucy/Test/Search/TestQueryParserSyntax.c      |   15 ++++++-----
 core/Lucy/Test/Search/TestQueryParserSyntax.cfh    |    2 +-
 core/Lucy/Test/Search/TestRangeQuery.c             |    3 +-
 core/Lucy/Test/Search/TestRangeQuery.cfh           |    2 +-
 core/Lucy/Test/Search/TestReqOptQuery.c            |    3 +-
 core/Lucy/Test/Search/TestReqOptQuery.cfh          |    2 +-
 core/Lucy/Test/Search/TestSeriesMatcher.c          |    3 +-
 core/Lucy/Test/Search/TestSeriesMatcher.cfh        |    2 +-
 core/Lucy/Test/Search/TestSortSpec.c               |    3 +-
 core/Lucy/Test/Search/TestSortSpec.cfh             |    2 +-
 core/Lucy/Test/Search/TestSpan.c                   |    3 +-
 core/Lucy/Test/Search/TestSpan.cfh                 |    2 +-
 core/Lucy/Test/Search/TestTermQuery.c              |    3 +-
 core/Lucy/Test/Search/TestTermQuery.cfh            |    2 +-
 core/Lucy/Test/Store/MockFileHandle.c              |    3 +-
 core/Lucy/Test/Store/MockFileHandle.cfh            |    2 +-
 core/Lucy/Test/Store/TestCompoundFileReader.c      |    1 +
 core/Lucy/Test/Store/TestCompoundFileReader.cfh    |    2 +-
 core/Lucy/Test/Store/TestCompoundFileWriter.c      |    1 +
 core/Lucy/Test/Store/TestCompoundFileWriter.cfh    |    2 +-
 core/Lucy/Test/Store/TestFSDirHandle.c             |    1 +
 core/Lucy/Test/Store/TestFSDirHandle.cfh           |    2 +-
 core/Lucy/Test/Store/TestFSFileHandle.c            |    1 +
 core/Lucy/Test/Store/TestFSFileHandle.cfh          |    2 +-
 core/Lucy/Test/Store/TestFSFolder.c                |    1 +
 core/Lucy/Test/Store/TestFSFolder.cfh              |    2 +-
 core/Lucy/Test/Store/TestFileHandle.c              |    3 +-
 core/Lucy/Test/Store/TestFileHandle.cfh            |    2 +-
 core/Lucy/Test/Store/TestFolder.c                  |    1 +
 core/Lucy/Test/Store/TestFolder.cfh                |    2 +-
 core/Lucy/Test/Store/TestFolderCommon.c            |    1 +
 core/Lucy/Test/Store/TestFolderCommon.cfh          |    2 +-
 core/Lucy/Test/Store/TestIOChunks.c                |    3 +-
 core/Lucy/Test/Store/TestIOChunks.cfh              |    2 +-
 core/Lucy/Test/Store/TestIOPrimitives.c            |    3 +-
 core/Lucy/Test/Store/TestIOPrimitives.cfh          |    2 +-
 core/Lucy/Test/Store/TestInStream.c                |    3 +-
 core/Lucy/Test/Store/TestInStream.cfh              |    2 +-
 core/Lucy/Test/Store/TestRAMDirHandle.c            |    1 +
 core/Lucy/Test/Store/TestRAMDirHandle.cfh          |    2 +-
 core/Lucy/Test/Store/TestRAMFileHandle.c           |    3 +-
 core/Lucy/Test/Store/TestRAMFileHandle.cfh         |    2 +-
 core/Lucy/Test/Store/TestRAMFolder.c               |    1 +
 core/Lucy/Test/Store/TestRAMFolder.cfh             |    2 +-
 core/Lucy/Test/TestSchema.c                        |    3 +-
 core/Lucy/Test/TestSchema.cfh                      |    2 +-
 core/Lucy/Test/TestUtils.c                         |    3 +-
 core/Lucy/Test/TestUtils.cfh                       |    2 +-
 core/Lucy/Test/Util/BBSortEx.c                     |    7 +++--
 core/Lucy/Test/Util/BBSortEx.cfh                   |    2 +-
 core/Lucy/Test/Util/TestIndexFileNames.c           |    1 +
 core/Lucy/Test/Util/TestIndexFileNames.cfh         |    2 +-
 core/Lucy/Test/Util/TestJson.c                     |    1 +
 core/Lucy/Test/Util/TestJson.cfh                   |    2 +-
 core/Lucy/Test/Util/TestMemoryPool.c               |    3 +-
 core/Lucy/Test/Util/TestMemoryPool.cfh             |    2 +-
 core/Lucy/Test/Util/TestPriorityQueue.c            |    3 +-
 core/Lucy/Test/Util/TestPriorityQueue.cfh          |    2 +-
 core/TestLucy.c                                    |   20 +++++++++++++++
 core/TestLucy.cfp                                  |    4 +++
 perl/Build.PL                                      |    4 ++-
 perl/buildlib/Lucy/Build/Binding/Misc.pm           |   20 +++++++-------
 137 files changed, 247 insertions(+), 138 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/c/t/test_lucy.c
----------------------------------------------------------------------
diff --git a/c/t/test_lucy.c b/c/t/test_lucy.c
index d7ba0bb..fc3f81e 100644
--- a/c/t/test_lucy.c
+++ b/c/t/test_lucy.c
@@ -26,11 +26,11 @@ main() {
     bool success = true;
 
     testcfish_bootstrap_parcel();
-    lucy_bootstrap_parcel();
+    testlucy_bootstrap_parcel();
 
     formatter = cfish_TestFormatterCF_new();
     success &= testcfish_Test_run_all_batches((cfish_TestFormatter*)formatter);
-    success &= lucy_Test_run_all_batches((cfish_TestFormatter*)formatter);
+    success &= testlucy_Test_run_all_batches((cfish_TestFormatter*)formatter);
     CFISH_DECREF(formatter);
 
     return success ? EXIT_SUCCESS : EXIT_FAILURE;

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/common/charmonizer.c b/common/charmonizer.c
index 81daf3f..89af398 100644
--- a/common/charmonizer.c
+++ b/common/charmonizer.c
@@ -6835,6 +6835,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
     chaz_CFlags_add_define(extra_cflags, "CFP_CFISH", NULL);
     chaz_CFlags_add_define(extra_cflags, "CFP_TESTCFISH", NULL);
     chaz_CFlags_add_define(extra_cflags, "CFP_LUCY", NULL);
+    chaz_CFlags_add_define(extra_cflags, "CFP_TESTLUCY", NULL);
 }
 
 static int
@@ -6997,6 +6998,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
                              "lucy_parcel", obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
+    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
+                             "testlucy_parcel", obj_ext, NULL);
+    chaz_MakeVar_append(var, scratch);
+    free(scratch);
 
     /* Clownfish header files */
 
@@ -7044,6 +7049,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
                              NULL);
     rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
     free(scratch);
+    scratch = chaz_Util_join(dir_sep, "autogen", "source", "testlucy_parcel.c",
+                             NULL);
+    rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
+    free(scratch);
 
     rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", "autogen");
     /*

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 539d0fb..815191f 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -93,6 +93,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
     chaz_CFlags_add_define(extra_cflags, "CFP_CFISH", NULL);
     chaz_CFlags_add_define(extra_cflags, "CFP_TESTCFISH", NULL);
     chaz_CFlags_add_define(extra_cflags, "CFP_LUCY", NULL);
+    chaz_CFlags_add_define(extra_cflags, "CFP_TESTLUCY", NULL);
 }
 
 static int
@@ -255,6 +256,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
                              "lucy_parcel", obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
+    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
+                             "testlucy_parcel", obj_ext, NULL);
+    chaz_MakeVar_append(var, scratch);
+    free(scratch);
 
     /* Clownfish header files */
 
@@ -302,6 +307,10 @@ S_write_makefile(struct chaz_CLIArgs *args) {
                              NULL);
     rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
     free(scratch);
+    scratch = chaz_Util_join(dir_sep, "autogen", "source", "testlucy_parcel.c",
+                             NULL);
+    rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
+    free(scratch);
 
     rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", "autogen");
     /*

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test.c b/core/Lucy/Test.c
index 19fef0e..ded5834 100644
--- a/core/Lucy/Test.c
+++ b/core/Lucy/Test.c
@@ -16,6 +16,7 @@
 
 #include <stdio.h>
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Lucy/Test.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test.cfh b/core/Lucy/Test.cfh
index 661b6a0..4c215bb 100644
--- a/core/Lucy/Test.cfh
+++ b/core/Lucy/Test.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** Testing framework.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestAnalyzer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestAnalyzer.c b/core/Lucy/Test/Analysis/TestAnalyzer.c
index 4b72f53..1443f8c 100644
--- a/core/Lucy/Test/Analysis/TestAnalyzer.c
+++ b/core/Lucy/Test/Analysis/TestAnalyzer.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestAnalyzer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestAnalyzer.cfh b/core/Lucy/Test/Analysis/TestAnalyzer.cfh
index ef9d042..78c0391 100644
--- a/core/Lucy/Test/Analysis/TestAnalyzer.cfh
+++ b/core/Lucy/Test/Analysis/TestAnalyzer.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Analysis::TestAnalyzer
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestCaseFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestCaseFolder.c b/core/Lucy/Test/Analysis/TestCaseFolder.c
index b428d38..8ee0f51 100644
--- a/core/Lucy/Test/Analysis/TestCaseFolder.c
+++ b/core/Lucy/Test/Analysis/TestCaseFolder.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTCASEFOLDER
+#define C_TESTLUCY_TESTCASEFOLDER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestCaseFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestCaseFolder.cfh b/core/Lucy/Test/Analysis/TestCaseFolder.cfh
index fa6d06e..087a5e1 100644
--- a/core/Lucy/Test/Analysis/TestCaseFolder.cfh
+++ b/core/Lucy/Test/Analysis/TestCaseFolder.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Analysis::TestCaseFolder
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestNormalizer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestNormalizer.c b/core/Lucy/Test/Analysis/TestNormalizer.c
index ca3e70d..94904d2 100644
--- a/core/Lucy/Test/Analysis/TestNormalizer.c
+++ b/core/Lucy/Test/Analysis/TestNormalizer.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTNORMALIZER
+#define C_TESTLUCY_TESTNORMALIZER
 #define C_LUCY_NORMALIZER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestNormalizer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestNormalizer.cfh b/core/Lucy/Test/Analysis/TestNormalizer.cfh
index 40e2917..cff80bc 100644
--- a/core/Lucy/Test/Analysis/TestNormalizer.cfh
+++ b/core/Lucy/Test/Analysis/TestNormalizer.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Analysis::TestNormalizer
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestPolyAnalyzer.c b/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
index 7c6178c..a1f3f8f 100644
--- a/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
+++ b/core/Lucy/Test/Analysis/TestPolyAnalyzer.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTPOLYANALYZER
+#define C_TESTLUCY_TESTPOLYANALYZER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh b/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
index e6f94f9..2e5319b 100644
--- a/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
+++ b/core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Analysis::TestPolyAnalyzer
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestRegexTokenizer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestRegexTokenizer.c b/core/Lucy/Test/Analysis/TestRegexTokenizer.c
index 4a97bf7..92b9b5b 100644
--- a/core/Lucy/Test/Analysis/TestRegexTokenizer.c
+++ b/core/Lucy/Test/Analysis/TestRegexTokenizer.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTREGEXTOKENIZER
+#define C_TESTLUCY_TESTREGEXTOKENIZER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh b/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
index bbaab59..8a23975 100644
--- a/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
+++ b/core/Lucy/Test/Analysis/TestRegexTokenizer.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Analysis::TestRegexTokenizer
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestSnowballStemmer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStemmer.c b/core/Lucy/Test/Analysis/TestSnowballStemmer.c
index 043e5ee..f045fe0 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStemmer.c
+++ b/core/Lucy/Test/Analysis/TestSnowballStemmer.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTSNOWBALLSTEMMER
+#define C_TESTLUCY_TESTSNOWBALLSTEMMER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh b/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
index 208d85b..f91aea4 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
+++ b/core/Lucy/Test/Analysis/TestSnowballStemmer.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Analysis::TestSnowballStemmer cnick TestSnowStemmer
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStopFilter.c b/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
index 3d11015..0e5663e 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
+++ b/core/Lucy/Test/Analysis/TestSnowballStopFilter.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTSNOWBALLSTOPFILTER
+#define C_TESTLUCY_TESTSNOWBALLSTOPFILTER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh b/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
index 6cb74e6..c80864b 100644
--- a/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
+++ b/core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Analysis::TestSnowballStopFilter cnick TestSnowStop
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestStandardTokenizer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestStandardTokenizer.c b/core/Lucy/Test/Analysis/TestStandardTokenizer.c
index 9e550a0..9f1775c 100644
--- a/core/Lucy/Test/Analysis/TestStandardTokenizer.c
+++ b/core/Lucy/Test/Analysis/TestStandardTokenizer.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTSTANDARDTOKENIZER
+#define C_TESTLUCY_TESTSTANDARDTOKENIZER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh b/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
index 0d45263..12f93b6 100644
--- a/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
+++ b/core/Lucy/Test/Analysis/TestStandardTokenizer.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Analysis::TestStandardTokenizer
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Highlight/TestHeatMap.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHeatMap.c b/core/Lucy/Test/Highlight/TestHeatMap.c
index 9e2bd37..08877e8 100644
--- a/core/Lucy/Test/Highlight/TestHeatMap.c
+++ b/core/Lucy/Test/Highlight/TestHeatMap.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Highlight/TestHeatMap.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHeatMap.cfh b/core/Lucy/Test/Highlight/TestHeatMap.cfh
index 4d1997b..8df87c9 100644
--- a/core/Lucy/Test/Highlight/TestHeatMap.cfh
+++ b/core/Lucy/Test/Highlight/TestHeatMap.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Highlight::TestHeatMap
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Highlight/TestHighlighter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHighlighter.c b/core/Lucy/Test/Highlight/TestHighlighter.c
index 769f22e..4194539 100644
--- a/core/Lucy/Test/Highlight/TestHighlighter.c
+++ b/core/Lucy/Test/Highlight/TestHighlighter.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTHIGHLIGHTER
+#define C_TESTLUCY_TESTHIGHLIGHTER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Highlight/TestHighlighter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Highlight/TestHighlighter.cfh b/core/Lucy/Test/Highlight/TestHighlighter.cfh
index 3ded317..6419bb9 100644
--- a/core/Lucy/Test/Highlight/TestHighlighter.cfh
+++ b/core/Lucy/Test/Highlight/TestHighlighter.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Highlight::TestHighlighter
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestDocWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestDocWriter.c b/core/Lucy/Test/Index/TestDocWriter.c
index 6af446e..b49a30f 100644
--- a/core/Lucy/Test/Index/TestDocWriter.c
+++ b/core/Lucy/Test/Index/TestDocWriter.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTDOCWRITER
+#define C_TESTLUCY_TESTDOCWRITER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestDocWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestDocWriter.cfh b/core/Lucy/Test/Index/TestDocWriter.cfh
index b43adf1..40403af 100644
--- a/core/Lucy/Test/Index/TestDocWriter.cfh
+++ b/core/Lucy/Test/Index/TestDocWriter.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Index::TestDocWriter
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestHighlightWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestHighlightWriter.c b/core/Lucy/Test/Index/TestHighlightWriter.c
index 821c6b1..e4152f6 100644
--- a/core/Lucy/Test/Index/TestHighlightWriter.c
+++ b/core/Lucy/Test/Index/TestHighlightWriter.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTHIGHLIGHTWRITER
+#define C_TESTLUCY_TESTHIGHLIGHTWRITER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestHighlightWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestHighlightWriter.cfh b/core/Lucy/Test/Index/TestHighlightWriter.cfh
index 7291f1b..7173c63 100644
--- a/core/Lucy/Test/Index/TestHighlightWriter.cfh
+++ b/core/Lucy/Test/Index/TestHighlightWriter.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Index::TestHighlightWriter cnick TestHLWriter
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestIndexManager.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestIndexManager.c b/core/Lucy/Test/Index/TestIndexManager.c
index 0aec551..aeda532 100644
--- a/core/Lucy/Test/Index/TestIndexManager.c
+++ b/core/Lucy/Test/Index/TestIndexManager.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestIndexManager.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestIndexManager.cfh b/core/Lucy/Test/Index/TestIndexManager.cfh
index 71e05bc..911afaa 100644
--- a/core/Lucy/Test/Index/TestIndexManager.cfh
+++ b/core/Lucy/Test/Index/TestIndexManager.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Index::TestIndexManager cnick TestIxManager
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestPolyReader.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPolyReader.c b/core/Lucy/Test/Index/TestPolyReader.c
index 5ec243b..58bd248 100644
--- a/core/Lucy/Test/Index/TestPolyReader.c
+++ b/core/Lucy/Test/Index/TestPolyReader.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTPOLYREADER
+#define C_TESTLUCY_TESTPOLYREADER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestPolyReader.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPolyReader.cfh b/core/Lucy/Test/Index/TestPolyReader.cfh
index 74b9456..1040439 100644
--- a/core/Lucy/Test/Index/TestPolyReader.cfh
+++ b/core/Lucy/Test/Index/TestPolyReader.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Index::TestPolyReader
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestPostingListWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPostingListWriter.c b/core/Lucy/Test/Index/TestPostingListWriter.c
index 09cbf20..27db6a8 100644
--- a/core/Lucy/Test/Index/TestPostingListWriter.c
+++ b/core/Lucy/Test/Index/TestPostingListWriter.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTPOSTINGLISTWRITER
+#define C_TESTLUCY_TESTPOSTINGLISTWRITER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestPostingListWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestPostingListWriter.cfh b/core/Lucy/Test/Index/TestPostingListWriter.cfh
index 8c5f5dd..353bdbe 100644
--- a/core/Lucy/Test/Index/TestPostingListWriter.cfh
+++ b/core/Lucy/Test/Index/TestPostingListWriter.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Index::TestPostingListWriter cnick TestPListWriter
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestSegWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegWriter.c b/core/Lucy/Test/Index/TestSegWriter.c
index 86801bf..e949c9d 100644
--- a/core/Lucy/Test/Index/TestSegWriter.c
+++ b/core/Lucy/Test/Index/TestSegWriter.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTSEGWRITER
+#define C_TESTLUCY_TESTSEGWRITER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestSegWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegWriter.cfh b/core/Lucy/Test/Index/TestSegWriter.cfh
index a55c877..471df86 100644
--- a/core/Lucy/Test/Index/TestSegWriter.cfh
+++ b/core/Lucy/Test/Index/TestSegWriter.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Index::TestSegWriter
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestSegment.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegment.c b/core/Lucy/Test/Index/TestSegment.c
index a802576..aa46dac 100644
--- a/core/Lucy/Test/Index/TestSegment.c
+++ b/core/Lucy/Test/Index/TestSegment.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTSEG
+#define C_TESTLUCY_TESTSEG
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestSegment.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSegment.cfh b/core/Lucy/Test/Index/TestSegment.cfh
index 237d843..76feab5 100644
--- a/core/Lucy/Test/Index/TestSegment.cfh
+++ b/core/Lucy/Test/Index/TestSegment.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Index::TestSegment cnick TestSeg
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestSnapshot.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSnapshot.c b/core/Lucy/Test/Index/TestSnapshot.c
index a0bbfa7..3e905cb 100644
--- a/core/Lucy/Test/Index/TestSnapshot.c
+++ b/core/Lucy/Test/Index/TestSnapshot.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestSnapshot.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestSnapshot.cfh b/core/Lucy/Test/Index/TestSnapshot.cfh
index 4be6876..4ecdf9d 100644
--- a/core/Lucy/Test/Index/TestSnapshot.cfh
+++ b/core/Lucy/Test/Index/TestSnapshot.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Index::TestSnapshot
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestTermInfo.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestTermInfo.c b/core/Lucy/Test/Index/TestTermInfo.c
index 9de3a08..3474e56 100644
--- a/core/Lucy/Test/Index/TestTermInfo.c
+++ b/core/Lucy/Test/Index/TestTermInfo.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTTERMINFO
+#define C_TESTLUCY_TESTTERMINFO
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Index/TestTermInfo.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Index/TestTermInfo.cfh b/core/Lucy/Test/Index/TestTermInfo.cfh
index c98bc30..6f7cb43 100644
--- a/core/Lucy/Test/Index/TestTermInfo.cfh
+++ b/core/Lucy/Test/Index/TestTermInfo.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Index::TestTermInfo
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Object/TestBitVector.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestBitVector.c b/core/Lucy/Test/Object/TestBitVector.c
index 6913d6b..cce4df9 100644
--- a/core/Lucy/Test/Object/TestBitVector.c
+++ b/core/Lucy/Test/Object/TestBitVector.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTBITVECTOR
+#define C_TESTLUCY_TESTBITVECTOR
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Object/TestBitVector.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestBitVector.cfh b/core/Lucy/Test/Object/TestBitVector.cfh
index 99a1338..75a1006 100644
--- a/core/Lucy/Test/Object/TestBitVector.cfh
+++ b/core/Lucy/Test/Object/TestBitVector.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Object::TestBitVector
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Object/TestI32Array.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestI32Array.c b/core/Lucy/Test/Object/TestI32Array.c
index 7c2550f..058d9ec 100644
--- a/core/Lucy/Test/Object/TestI32Array.c
+++ b/core/Lucy/Test/Object/TestI32Array.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTI32ARRAY
+#define C_TESTLUCY_TESTI32ARRAY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Object/TestI32Array.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Object/TestI32Array.cfh b/core/Lucy/Test/Object/TestI32Array.cfh
index 1f03ccb..7f5c19f 100644
--- a/core/Lucy/Test/Object/TestI32Array.cfh
+++ b/core/Lucy/Test/Object/TestI32Array.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Object::TestI32Array cnick TestI32Arr
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestArchitecture.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestArchitecture.c b/core/Lucy/Test/Plan/TestArchitecture.c
index cdc64e0..9cd2636 100644
--- a/core/Lucy/Test/Plan/TestArchitecture.c
+++ b/core/Lucy/Test/Plan/TestArchitecture.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTARCHITECTURE
+#define C_TESTLUCY_TESTARCHITECTURE
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Lucy/Test.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestArchitecture.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestArchitecture.cfh b/core/Lucy/Test/Plan/TestArchitecture.cfh
index c80c00c..9d227e1 100644
--- a/core/Lucy/Test/Plan/TestArchitecture.cfh
+++ b/core/Lucy/Test/Plan/TestArchitecture.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /**
  * Returns absurdly low values for Index_Interval() and Skip_Interval().

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestBlobType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestBlobType.c b/core/Lucy/Test/Plan/TestBlobType.c
index eec3127..2012088 100644
--- a/core/Lucy/Test/Plan/TestBlobType.c
+++ b/core/Lucy/Test/Plan/TestBlobType.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTBLOBTYPE
+#define C_TESTLUCY_TESTBLOBTYPE
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestBlobType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestBlobType.cfh b/core/Lucy/Test/Plan/TestBlobType.cfh
index 42f76cd..8ec6fc1 100644
--- a/core/Lucy/Test/Plan/TestBlobType.cfh
+++ b/core/Lucy/Test/Plan/TestBlobType.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Plan::TestBlobType
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestFieldMisc.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldMisc.c b/core/Lucy/Test/Plan/TestFieldMisc.c
index 6cb5f23..bd39cc4 100644
--- a/core/Lucy/Test/Plan/TestFieldMisc.c
+++ b/core/Lucy/Test/Plan/TestFieldMisc.c
@@ -15,6 +15,7 @@
  */
 
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include "Clownfish/Test/TestFormatter.h"
 #include "Lucy/Test.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestFieldMisc.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldMisc.cfh b/core/Lucy/Test/Plan/TestFieldMisc.cfh
index 8d57777..98734b8 100644
--- a/core/Lucy/Test/Plan/TestFieldMisc.cfh
+++ b/core/Lucy/Test/Plan/TestFieldMisc.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Plan::TestFieldMisc
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestFieldType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldType.c b/core/Lucy/Test/Plan/TestFieldType.c
index d160f45..e2ce6b2 100644
--- a/core/Lucy/Test/Plan/TestFieldType.c
+++ b/core/Lucy/Test/Plan/TestFieldType.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTFIELDTYPE
+#define C_TESTLUCY_TESTFIELDTYPE
 #define C_LUCY_DUMMYFIELDTYPE
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestFieldType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFieldType.cfh b/core/Lucy/Test/Plan/TestFieldType.cfh
index 0a0ec65..f91ec94 100644
--- a/core/Lucy/Test/Plan/TestFieldType.cfh
+++ b/core/Lucy/Test/Plan/TestFieldType.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Plan::TestFieldType cnick TestFType
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestFullTextType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFullTextType.c b/core/Lucy/Test/Plan/TestFullTextType.c
index 9ee470e..cf8ef8f 100644
--- a/core/Lucy/Test/Plan/TestFullTextType.c
+++ b/core/Lucy/Test/Plan/TestFullTextType.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTFULLTEXTTYPE
+#define C_TESTLUCY_TESTFULLTEXTTYPE
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestFullTextType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestFullTextType.cfh b/core/Lucy/Test/Plan/TestFullTextType.cfh
index 031be31..91b9f30 100644
--- a/core/Lucy/Test/Plan/TestFullTextType.cfh
+++ b/core/Lucy/Test/Plan/TestFullTextType.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Plan::TestFullTextType
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestNumericType.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestNumericType.c b/core/Lucy/Test/Plan/TestNumericType.c
index c1f554d..cdc42b5 100644
--- a/core/Lucy/Test/Plan/TestNumericType.c
+++ b/core/Lucy/Test/Plan/TestNumericType.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTNUMERICTYPE
+#define C_TESTLUCY_TESTNUMERICTYPE
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Plan/TestNumericType.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Plan/TestNumericType.cfh b/core/Lucy/Test/Plan/TestNumericType.cfh
index f411aff..72f7823 100644
--- a/core/Lucy/Test/Plan/TestNumericType.cfh
+++ b/core/Lucy/Test/Plan/TestNumericType.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Plan::TestNumericType
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestLeafQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestLeafQuery.c b/core/Lucy/Test/Search/TestLeafQuery.c
index 8381fd6..7dd37f8 100644
--- a/core/Lucy/Test/Search/TestLeafQuery.c
+++ b/core/Lucy/Test/Search/TestLeafQuery.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTLEAFQUERY
+#define C_TESTLUCY_TESTLEAFQUERY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestLeafQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestLeafQuery.cfh b/core/Lucy/Test/Search/TestLeafQuery.cfh
index 4fc8a37..7bb03ab 100644
--- a/core/Lucy/Test/Search/TestLeafQuery.cfh
+++ b/core/Lucy/Test/Search/TestLeafQuery.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestLeafQuery
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestMatchAllQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestMatchAllQuery.c b/core/Lucy/Test/Search/TestMatchAllQuery.c
index ec95b62..57f395b 100644
--- a/core/Lucy/Test/Search/TestMatchAllQuery.c
+++ b/core/Lucy/Test/Search/TestMatchAllQuery.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTMATCHALLQUERY
+#define C_TESTLUCY_TESTMATCHALLQUERY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestMatchAllQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestMatchAllQuery.cfh b/core/Lucy/Test/Search/TestMatchAllQuery.cfh
index 8f66e34..1f09bc1 100644
--- a/core/Lucy/Test/Search/TestMatchAllQuery.cfh
+++ b/core/Lucy/Test/Search/TestMatchAllQuery.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestMatchAllQuery
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestNOTQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNOTQuery.c b/core/Lucy/Test/Search/TestNOTQuery.c
index 58c7f4a..374fd3d 100644
--- a/core/Lucy/Test/Search/TestNOTQuery.c
+++ b/core/Lucy/Test/Search/TestNOTQuery.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTNOTQUERY
+#define C_TESTLUCY_TESTNOTQUERY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestNOTQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNOTQuery.cfh b/core/Lucy/Test/Search/TestNOTQuery.cfh
index 38a138a..becf64e 100644
--- a/core/Lucy/Test/Search/TestNOTQuery.cfh
+++ b/core/Lucy/Test/Search/TestNOTQuery.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestNOTQuery
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestNoMatchQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNoMatchQuery.c b/core/Lucy/Test/Search/TestNoMatchQuery.c
index 94fb3d3..a1a9e20 100644
--- a/core/Lucy/Test/Search/TestNoMatchQuery.c
+++ b/core/Lucy/Test/Search/TestNoMatchQuery.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTNOMATCHQUERY
+#define C_TESTLUCY_TESTNOMATCHQUERY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestNoMatchQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestNoMatchQuery.cfh b/core/Lucy/Test/Search/TestNoMatchQuery.cfh
index 3e679ad..a283efa 100644
--- a/core/Lucy/Test/Search/TestNoMatchQuery.cfh
+++ b/core/Lucy/Test/Search/TestNoMatchQuery.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestNoMatchQuery
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestPhraseQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPhraseQuery.c b/core/Lucy/Test/Search/TestPhraseQuery.c
index 6759b49..3f07f9d 100644
--- a/core/Lucy/Test/Search/TestPhraseQuery.c
+++ b/core/Lucy/Test/Search/TestPhraseQuery.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTPHRASEQUERY
+#define C_TESTLUCY_TESTPHRASEQUERY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestPhraseQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPhraseQuery.cfh b/core/Lucy/Test/Search/TestPhraseQuery.cfh
index e183818..c39290a 100644
--- a/core/Lucy/Test/Search/TestPhraseQuery.cfh
+++ b/core/Lucy/Test/Search/TestPhraseQuery.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestPhraseQuery
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestPolyQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPolyQuery.c b/core/Lucy/Test/Search/TestPolyQuery.c
index 93b560c..531bb3c 100644
--- a/core/Lucy/Test/Search/TestPolyQuery.c
+++ b/core/Lucy/Test/Search/TestPolyQuery.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTPOLYQUERY
+#define C_TESTLUCY_TESTPOLYQUERY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestPolyQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestPolyQuery.cfh b/core/Lucy/Test/Search/TestPolyQuery.cfh
index fbc1f24..768e8c4 100644
--- a/core/Lucy/Test/Search/TestPolyQuery.cfh
+++ b/core/Lucy/Test/Search/TestPolyQuery.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestANDQuery
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestQueryParser.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParser.c b/core/Lucy/Test/Search/TestQueryParser.c
index 3a25afe..665b275 100644
--- a/core/Lucy/Test/Search/TestQueryParser.c
+++ b/core/Lucy/Test/Search/TestQueryParser.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTQUERYPARSER
+#define C_TESTLUCY_TESTQUERYPARSER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <string.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestQueryParser.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParser.cfh b/core/Lucy/Test/Search/TestQueryParser.cfh
index cbf711a..62b9c74 100644
--- a/core/Lucy/Test/Search/TestQueryParser.cfh
+++ b/core/Lucy/Test/Search/TestQueryParser.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** Test case object for QueryParser unit tests.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestQueryParserLogic.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserLogic.c b/core/Lucy/Test/Search/TestQueryParserLogic.c
index 02b398e..0d88816 100644
--- a/core/Lucy/Test/Search/TestQueryParserLogic.c
+++ b/core/Lucy/Test/Search/TestQueryParserLogic.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTQUERYPARSERLOGIC
-#define C_LUCY_TESTQUERYPARSER
+#define C_TESTLUCY_TESTQUERYPARSERLOGIC
+#define C_TESTLUCY_TESTQUERYPARSER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <string.h>
 
@@ -42,9 +43,9 @@
 #include "Lucy/Search/RequiredOptionalQuery.h"
 #include "Lucy/Store/RAMFolder.h"
 
-#define make_leaf_query   (Query*)lucy_TestUtils_make_leaf_query
-#define make_not_query    (Query*)lucy_TestUtils_make_not_query
-#define make_poly_query   (Query*)lucy_TestUtils_make_poly_query
+#define make_leaf_query   (Query*)TestUtils_make_leaf_query
+#define make_not_query    (Query*)TestUtils_make_not_query
+#define make_poly_query   (Query*)TestUtils_make_poly_query
 
 TestQueryParserLogic*
 TestQPLogic_new(TestFormatter *formatter) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestQueryParserLogic.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserLogic.cfh b/core/Lucy/Test/Search/TestQueryParserLogic.cfh
index 94f1486..5f28b54 100644
--- a/core/Lucy/Test/Search/TestQueryParserLogic.cfh
+++ b/core/Lucy/Test/Search/TestQueryParserLogic.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** Tests for logical structure of Query objects output by QueryParser.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestQueryParserSyntax.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserSyntax.c b/core/Lucy/Test/Search/TestQueryParserSyntax.c
index dd209e3..ededff1 100644
--- a/core/Lucy/Test/Search/TestQueryParserSyntax.c
+++ b/core/Lucy/Test/Search/TestQueryParserSyntax.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTQUERYPARSERSYNTAX
-#define C_LUCY_TESTQUERYPARSER
+#define C_TESTLUCY_TESTQUERYPARSERSYNTAX
+#define C_TESTLUCY_TESTQUERYPARSER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <string.h>
 
@@ -43,11 +44,11 @@
 #include "Lucy/Store/Folder.h"
 #include "Lucy/Store/RAMFolder.h"
 
-#define make_term_query   (Query*)lucy_TestUtils_make_term_query
-#define make_phrase_query (Query*)lucy_TestUtils_make_phrase_query
-#define make_leaf_query   (Query*)lucy_TestUtils_make_leaf_query
-#define make_not_query    (Query*)lucy_TestUtils_make_not_query
-#define make_poly_query   (Query*)lucy_TestUtils_make_poly_query
+#define make_term_query   (Query*)TestUtils_make_term_query
+#define make_phrase_query (Query*)TestUtils_make_phrase_query
+#define make_leaf_query   (Query*)TestUtils_make_leaf_query
+#define make_not_query    (Query*)TestUtils_make_not_query
+#define make_poly_query   (Query*)TestUtils_make_poly_query
 
 TestQueryParserSyntax*
 TestQPSyntax_new(TestFormatter *formatter) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestQueryParserSyntax.cfh b/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
index 6b12d9d..794dbe7 100644
--- a/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
+++ b/core/Lucy/Test/Search/TestQueryParserSyntax.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** Tests for logical structure of Query objects output by QueryParser.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestRangeQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestRangeQuery.c b/core/Lucy/Test/Search/TestRangeQuery.c
index 8fc75ed..7d76eee 100644
--- a/core/Lucy/Test/Search/TestRangeQuery.c
+++ b/core/Lucy/Test/Search/TestRangeQuery.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTRANGEQUERY
+#define C_TESTLUCY_TESTRANGEQUERY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestRangeQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestRangeQuery.cfh b/core/Lucy/Test/Search/TestRangeQuery.cfh
index d885f29..41e98d3 100644
--- a/core/Lucy/Test/Search/TestRangeQuery.cfh
+++ b/core/Lucy/Test/Search/TestRangeQuery.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestRangeQuery
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestReqOptQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestReqOptQuery.c b/core/Lucy/Test/Search/TestReqOptQuery.c
index 097cee3..f32bc5d 100644
--- a/core/Lucy/Test/Search/TestReqOptQuery.c
+++ b/core/Lucy/Test/Search/TestReqOptQuery.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTREQOPTQUERY
+#define C_TESTLUCY_TESTREQOPTQUERY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestReqOptQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestReqOptQuery.cfh b/core/Lucy/Test/Search/TestReqOptQuery.cfh
index 7011ebe..b783734 100644
--- a/core/Lucy/Test/Search/TestReqOptQuery.cfh
+++ b/core/Lucy/Test/Search/TestReqOptQuery.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestReqOptQuery
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestSeriesMatcher.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSeriesMatcher.c b/core/Lucy/Test/Search/TestSeriesMatcher.c
index 1c0c297..e3e68db 100644
--- a/core/Lucy/Test/Search/TestSeriesMatcher.c
+++ b/core/Lucy/Test/Search/TestSeriesMatcher.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTSERIESMATCHER
+#define C_TESTLUCY_TESTSERIESMATCHER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestSeriesMatcher.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSeriesMatcher.cfh b/core/Lucy/Test/Search/TestSeriesMatcher.cfh
index 00c6c11..5952ce6 100644
--- a/core/Lucy/Test/Search/TestSeriesMatcher.cfh
+++ b/core/Lucy/Test/Search/TestSeriesMatcher.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestSeriesMatcher
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestSortSpec.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSortSpec.c b/core/Lucy/Test/Search/TestSortSpec.c
index 5836293..a8b1e3e 100644
--- a/core/Lucy/Test/Search/TestSortSpec.c
+++ b/core/Lucy/Test/Search/TestSortSpec.c
@@ -15,7 +15,8 @@
  */
 
 
-#define C_LUCY_TESTREVERSETYPE
+#define C_TESTLUCY_TESTREVERSETYPE
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <stdio.h>
 #include <stdlib.h>

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestSortSpec.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSortSpec.cfh b/core/Lucy/Test/Search/TestSortSpec.cfh
index 7d96228..633b452 100644
--- a/core/Lucy/Test/Search/TestSortSpec.cfh
+++ b/core/Lucy/Test/Search/TestSortSpec.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestSortSpec
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestSpan.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSpan.c b/core/Lucy/Test/Search/TestSpan.c
index 2dd41a6..d359dbe 100644
--- a/core/Lucy/Test/Search/TestSpan.c
+++ b/core/Lucy/Test/Search/TestSpan.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTTERMINFO
+#define C_TESTLUCY_TESTTERMINFO
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestSpan.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestSpan.cfh b/core/Lucy/Test/Search/TestSpan.cfh
index 83a91ef..1c9a119 100644
--- a/core/Lucy/Test/Search/TestSpan.cfh
+++ b/core/Lucy/Test/Search/TestSpan.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestSpan
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestTermQuery.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestTermQuery.c b/core/Lucy/Test/Search/TestTermQuery.c
index 65291b2..809c440 100644
--- a/core/Lucy/Test/Search/TestTermQuery.c
+++ b/core/Lucy/Test/Search/TestTermQuery.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTTERMQUERY
+#define C_TESTLUCY_TESTTERMQUERY
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <math.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Search/TestTermQuery.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Search/TestTermQuery.cfh b/core/Lucy/Test/Search/TestTermQuery.cfh
index b8ecf6a..96e5d09 100644
--- a/core/Lucy/Test/Search/TestTermQuery.cfh
+++ b/core/Lucy/Test/Search/TestTermQuery.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Search::TestTermQuery
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/MockFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/MockFileHandle.c b/core/Lucy/Test/Store/MockFileHandle.c
index 09df022..3e3ba04 100644
--- a/core/Lucy/Test/Store/MockFileHandle.c
+++ b/core/Lucy/Test/Store/MockFileHandle.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_MOCKFILEHANDLE
+#define C_TESTLUCY_MOCKFILEHANDLE
 #define C_LUCY_FILEWINDOW
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Lucy/Test/Store/MockFileHandle.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/MockFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/MockFileHandle.cfh b/core/Lucy/Test/Store/MockFileHandle.cfh
index b142c00..a88468f 100644
--- a/core/Lucy/Test/Store/MockFileHandle.cfh
+++ b/core/Lucy/Test/Store/MockFileHandle.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** Mock-object FileHandle for testing InStream/OutStream.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestCompoundFileReader.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileReader.c b/core/Lucy/Test/Store/TestCompoundFileReader.c
index 101b5a0..f3748be 100644
--- a/core/Lucy/Test/Store/TestCompoundFileReader.c
+++ b/core/Lucy/Test/Store/TestCompoundFileReader.c
@@ -15,6 +15,7 @@
  */
 
 #define C_LUCY_RAMFOLDER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestCompoundFileReader.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileReader.cfh b/core/Lucy/Test/Store/TestCompoundFileReader.cfh
index fb2e300..f12c05b 100644
--- a/core/Lucy/Test/Store/TestCompoundFileReader.cfh
+++ b/core/Lucy/Test/Store/TestCompoundFileReader.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestCompoundFileReader cnick TestCFReader
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestCompoundFileWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileWriter.c b/core/Lucy/Test/Store/TestCompoundFileWriter.c
index e2b9281..76dc72c 100644
--- a/core/Lucy/Test/Store/TestCompoundFileWriter.c
+++ b/core/Lucy/Test/Store/TestCompoundFileWriter.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestCompoundFileWriter.cfh b/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
index 073aee8..f1ca473 100644
--- a/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
+++ b/core/Lucy/Test/Store/TestCompoundFileWriter.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestCompoundFileWriter cnick TestCFWriter
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFSDirHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSDirHandle.c b/core/Lucy/Test/Store/TestFSDirHandle.c
index 4c9ea2d..da9f9ff 100644
--- a/core/Lucy/Test/Store/TestFSDirHandle.c
+++ b/core/Lucy/Test/Store/TestFSDirHandle.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 // rmdir

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFSDirHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSDirHandle.cfh b/core/Lucy/Test/Store/TestFSDirHandle.cfh
index e12601b..d76dabb 100644
--- a/core/Lucy/Test/Store/TestFSDirHandle.cfh
+++ b/core/Lucy/Test/Store/TestFSDirHandle.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestFSDirHandle cnick TestFSDH
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFSFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFileHandle.c b/core/Lucy/Test/Store/TestFSFileHandle.c
index b9aec6c..34048a3 100644
--- a/core/Lucy/Test/Store/TestFSFileHandle.c
+++ b/core/Lucy/Test/Store/TestFSFileHandle.c
@@ -18,6 +18,7 @@
 
 #define C_LUCY_FSFILEHANDLE
 #define C_LUCY_FILEWINDOW
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #ifdef CHY_HAS_UNISTD_H

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFSFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFileHandle.cfh b/core/Lucy/Test/Store/TestFSFileHandle.cfh
index 6a7e7f4..6fd288c 100644
--- a/core/Lucy/Test/Store/TestFSFileHandle.cfh
+++ b/core/Lucy/Test/Store/TestFSFileHandle.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestFSFileHandle cnick TestFSFH
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFSFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFolder.c b/core/Lucy/Test/Store/TestFSFolder.c
index 74165ff..d85deef 100644
--- a/core/Lucy/Test/Store/TestFSFolder.c
+++ b/core/Lucy/Test/Store/TestFSFolder.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 // mkdir, rmdir

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFSFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFSFolder.cfh b/core/Lucy/Test/Store/TestFSFolder.cfh
index 0793c88..896e813 100644
--- a/core/Lucy/Test/Store/TestFSFolder.cfh
+++ b/core/Lucy/Test/Store/TestFSFolder.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestFSFolder
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFileHandle.c b/core/Lucy/Test/Store/TestFileHandle.c
index 1c54276..645b516 100644
--- a/core/Lucy/Test/Store/TestFileHandle.c
+++ b/core/Lucy/Test/Store/TestFileHandle.c
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTINSTREAM
+#define C_TESTLUCY_TESTINSTREAM
 #define C_LUCY_INSTREAM
 #define C_LUCY_FILEWINDOW
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFileHandle.cfh b/core/Lucy/Test/Store/TestFileHandle.cfh
index 6f24a6a..8e852ba 100644
--- a/core/Lucy/Test/Store/TestFileHandle.cfh
+++ b/core/Lucy/Test/Store/TestFileHandle.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestFileHandle cnick TestFH
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolder.c b/core/Lucy/Test/Store/TestFolder.c
index 1de7699..75eb6e6 100644
--- a/core/Lucy/Test/Store/TestFolder.c
+++ b/core/Lucy/Test/Store/TestFolder.c
@@ -15,6 +15,7 @@
  */
 
 #define C_LUCY_RAMFOLDER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolder.cfh b/core/Lucy/Test/Store/TestFolder.cfh
index 37af079..09e4c2b 100644
--- a/core/Lucy/Test/Store/TestFolder.cfh
+++ b/core/Lucy/Test/Store/TestFolder.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestFolder
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFolderCommon.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolderCommon.c b/core/Lucy/Test/Store/TestFolderCommon.c
index b10a6ff..ddbb421 100644
--- a/core/Lucy/Test/Store/TestFolderCommon.c
+++ b/core/Lucy/Test/Store/TestFolderCommon.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Lucy/Test.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestFolderCommon.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestFolderCommon.cfh b/core/Lucy/Test/Store/TestFolderCommon.cfh
index 26dbdc8..f072ce9 100644
--- a/core/Lucy/Test/Store/TestFolderCommon.cfh
+++ b/core/Lucy/Test/Store/TestFolderCommon.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 __C__
 typedef lucy_Folder*

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestIOChunks.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOChunks.c b/core/Lucy/Test/Store/TestIOChunks.c
index ffaf148..3f88a3d 100644
--- a/core/Lucy/Test/Store/TestIOChunks.c
+++ b/core/Lucy/Test/Store/TestIOChunks.c
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTINSTREAM
+#define C_TESTLUCY_TESTINSTREAM
 #define C_LUCY_INSTREAM
 #define C_LUCY_FILEWINDOW
 #include <stdlib.h>
 #include <time.h>
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include "Clownfish/Test/TestFormatter.h"
 #include "Lucy/Test.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestIOChunks.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOChunks.cfh b/core/Lucy/Test/Store/TestIOChunks.cfh
index 753ad19..94e5813 100644
--- a/core/Lucy/Test/Store/TestIOChunks.cfh
+++ b/core/Lucy/Test/Store/TestIOChunks.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** Tests reading and writing of composite types using InStream/OutStream.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestIOPrimitives.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOPrimitives.c b/core/Lucy/Test/Store/TestIOPrimitives.c
index 542655e..009043b 100644
--- a/core/Lucy/Test/Store/TestIOPrimitives.c
+++ b/core/Lucy/Test/Store/TestIOPrimitives.c
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTINSTREAM
+#define C_TESTLUCY_TESTINSTREAM
 #define C_LUCY_INSTREAM
 #define C_LUCY_FILEWINDOW
 #include <stdlib.h>
 #include <time.h>
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include "Clownfish/Test/TestFormatter.h"
 #include "Lucy/Test.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestIOPrimitives.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestIOPrimitives.cfh b/core/Lucy/Test/Store/TestIOPrimitives.cfh
index dddd202..106f940 100644
--- a/core/Lucy/Test/Store/TestIOPrimitives.cfh
+++ b/core/Lucy/Test/Store/TestIOPrimitives.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** Tests reading and writing of primitive types using InStream/OutStream.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestInStream.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestInStream.c b/core/Lucy/Test/Store/TestInStream.c
index e15139f..95b2cb1 100644
--- a/core/Lucy/Test/Store/TestInStream.c
+++ b/core/Lucy/Test/Store/TestInStream.c
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTINSTREAM
+#define C_TESTLUCY_TESTINSTREAM
 #define C_LUCY_INSTREAM
 #define C_LUCY_FILEWINDOW
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include "Clownfish/Test/TestFormatter.h"
 #include "Lucy/Test.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestInStream.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestInStream.cfh b/core/Lucy/Test/Store/TestInStream.cfh
index b20668d..5052685 100644
--- a/core/Lucy/Test/Store/TestInStream.cfh
+++ b/core/Lucy/Test/Store/TestInStream.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** Tests for basic functionality of InStream using both memory-mapped and
  * streamed sources.

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestRAMDirHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMDirHandle.c b/core/Lucy/Test/Store/TestRAMDirHandle.c
index 69e3e28..fcdcd1a 100644
--- a/core/Lucy/Test/Store/TestRAMDirHandle.c
+++ b/core/Lucy/Test/Store/TestRAMDirHandle.c
@@ -15,6 +15,7 @@
  */
 
 #define C_LUCY_RAMFOLDER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestRAMDirHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMDirHandle.cfh b/core/Lucy/Test/Store/TestRAMDirHandle.cfh
index 460889c..aabe232 100644
--- a/core/Lucy/Test/Store/TestRAMDirHandle.cfh
+++ b/core/Lucy/Test/Store/TestRAMDirHandle.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestRAMDirHandle cnick TestRAMDH
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestRAMFileHandle.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFileHandle.c b/core/Lucy/Test/Store/TestRAMFileHandle.c
index 7c7df13..5d75bc3 100644
--- a/core/Lucy/Test/Store/TestRAMFileHandle.c
+++ b/core/Lucy/Test/Store/TestRAMFileHandle.c
@@ -16,9 +16,10 @@
 
 #include <string.h>
 
-#define C_LUCY_TESTINSTREAM
+#define C_TESTLUCY_TESTINSTREAM
 #define C_LUCY_INSTREAM
 #define C_LUCY_FILEWINDOW
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestRAMFileHandle.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFileHandle.cfh b/core/Lucy/Test/Store/TestRAMFileHandle.cfh
index 87fa5bc..8ee2c1d 100644
--- a/core/Lucy/Test/Store/TestRAMFileHandle.cfh
+++ b/core/Lucy/Test/Store/TestRAMFileHandle.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestRAMFileHandle cnick TestRAMFH
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestRAMFolder.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFolder.c b/core/Lucy/Test/Store/TestRAMFolder.c
index 0261fe3..0446e9d 100644
--- a/core/Lucy/Test/Store/TestRAMFolder.c
+++ b/core/Lucy/Test/Store/TestRAMFolder.c
@@ -15,6 +15,7 @@
  */
 
 #define C_LUCY_RAMFOLDER
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Store/TestRAMFolder.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Store/TestRAMFolder.cfh b/core/Lucy/Test/Store/TestRAMFolder.cfh
index b1877b6..dfc3864 100644
--- a/core/Lucy/Test/Store/TestRAMFolder.cfh
+++ b/core/Lucy/Test/Store/TestRAMFolder.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Store::TestRAMFolder
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/TestSchema.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestSchema.c b/core/Lucy/Test/TestSchema.c
index 0fe51b3..34029cd 100644
--- a/core/Lucy/Test/TestSchema.c
+++ b/core/Lucy/Test/TestSchema.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTSCHEMA
+#define C_TESTLUCY_TESTSCHEMA
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/TestSchema.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestSchema.cfh b/core/Lucy/Test/TestSchema.cfh
index 9296edc..decb6d5 100644
--- a/core/Lucy/Test/TestSchema.cfh
+++ b/core/Lucy/Test/TestSchema.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** Schema for use by the test suite.
  *

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/TestUtils.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestUtils.c b/core/Lucy/Test/TestUtils.c
index e724694..d567e15 100644
--- a/core/Lucy/Test/TestUtils.c
+++ b/core/Lucy/Test/TestUtils.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTUTILS
+#define C_TESTLUCY_TESTUTILS
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 #include <string.h>
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/TestUtils.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/TestUtils.cfh b/core/Lucy/Test/TestUtils.cfh
index 5fb5d77..23c55c5 100644
--- a/core/Lucy/Test/TestUtils.cfh
+++ b/core/Lucy/Test/TestUtils.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 inert class Lucy::Test::TestUtils  {
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/BBSortEx.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/BBSortEx.c b/core/Lucy/Test/Util/BBSortEx.c
index ad5bad8..cdff551 100644
--- a/core/Lucy/Test/Util/BBSortEx.c
+++ b/core/Lucy/Test/Util/BBSortEx.c
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define C_LUCY_BBSORTEX
+#define C_TESTLUCY_BBSORTEX
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Lucy/Test/Util/BBSortEx.h"
@@ -54,14 +55,14 @@ BBSortEx_clear_cache(BBSortEx *self) {
     }
     self->mem_consumed = 0;
     BBSortEx_Clear_Cache_t super_clear_cache
-        = SUPER_METHOD_PTR(BBSORTEX, Lucy_BBSortEx_Clear_Cache);
+        = SUPER_METHOD_PTR(BBSORTEX, TestLucy_BBSortEx_Clear_Cache);
     super_clear_cache(self);
 }
 
 void
 BBSortEx_feed(BBSortEx *self, void *data) {
     BBSortEx_Feed_t super_feed
-        = SUPER_METHOD_PTR(BBSORTEX, Lucy_BBSortEx_Feed);
+        = SUPER_METHOD_PTR(BBSORTEX, TestLucy_BBSortEx_Feed);
     super_feed(self, data);
 
     // Flush() if necessary.

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/BBSortEx.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/BBSortEx.cfh b/core/Lucy/Test/Util/BBSortEx.cfh
index f82954f..1978085 100644
--- a/core/Lucy/Test/Util/BBSortEx.cfh
+++ b/core/Lucy/Test/Util/BBSortEx.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 /** SortExternal for ByteBufs.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/TestIndexFileNames.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestIndexFileNames.c b/core/Lucy/Test/Util/TestIndexFileNames.c
index d98b92c..95e0f3f 100644
--- a/core/Lucy/Test/Util/TestIndexFileNames.c
+++ b/core/Lucy/Test/Util/TestIndexFileNames.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/TestIndexFileNames.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestIndexFileNames.cfh b/core/Lucy/Test/Util/TestIndexFileNames.cfh
index 5702eb4..8e106b7 100644
--- a/core/Lucy/Test/Util/TestIndexFileNames.cfh
+++ b/core/Lucy/Test/Util/TestIndexFileNames.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Util::TestIndexFileNames cnick TestIxFileNames
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/TestJson.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestJson.c b/core/Lucy/Test/Util/TestJson.c
index cc3a872..6d379a2 100644
--- a/core/Lucy/Test/Util/TestJson.c
+++ b/core/Lucy/Test/Util/TestJson.c
@@ -15,6 +15,7 @@
  */
 
 #include <string.h>
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/TestJson.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestJson.cfh b/core/Lucy/Test/Util/TestJson.cfh
index c7728c1..0bf2e2f 100644
--- a/core/Lucy/Test/Util/TestJson.cfh
+++ b/core/Lucy/Test/Util/TestJson.cfh
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-parcel Lucy;
+parcel TestLucy;
 
 class Lucy::Test::Util::TestJson
     inherits Clownfish::Test::TestBatch {

http://git-wip-us.apache.org/repos/asf/lucy/blob/ffb0e921/core/Lucy/Test/Util/TestMemoryPool.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestMemoryPool.c b/core/Lucy/Test/Util/TestMemoryPool.c
index 4c9d96c..b7a63ae 100644
--- a/core/Lucy/Test/Util/TestMemoryPool.c
+++ b/core/Lucy/Test/Util/TestMemoryPool.c
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#define C_LUCY_TESTMEMORYPOOL
+#define C_TESTLUCY_TESTMEMORYPOOL
 #define C_LUCY_MEMORYPOOL
+#define TESTLUCY_USE_SHORT_NAMES
 #include "Lucy/Util/ToolSet.h"
 
 #include "Clownfish/Test/TestFormatter.h"


[lucy-commits] [10/26] git commit: refs/heads/separate-clownfish-wip2 - Remove CFCParcel_clownfish_parcel

Posted by nw...@apache.org.
Remove CFCParcel_clownfish_parcel

It's only used in CFCDumpable.c and there it's actually used wrongly.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/cecd5242
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/cecd5242
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/cecd5242

Branch: refs/heads/separate-clownfish-wip2
Commit: cecd52426ec89620863ae520c847ae5bb9d8175a
Parents: 4d9f129
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sun May 26 16:36:50 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:30:17 2013 +0200

----------------------------------------------------------------------
 clownfish/compiler/src/CFCDumpable.c |    5 ++---
 clownfish/compiler/src/CFCParcel.c   |   13 -------------
 clownfish/compiler/src/CFCParcel.h   |    7 -------
 clownfish/compiler/src/CFCType.h     |    3 +++
 4 files changed, 5 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/cecd5242/clownfish/compiler/src/CFCDumpable.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCDumpable.c b/clownfish/compiler/src/CFCDumpable.c
index a8230cd..7fd2616 100644
--- a/clownfish/compiler/src/CFCDumpable.c
+++ b/clownfish/compiler/src/CFCDumpable.c
@@ -114,10 +114,9 @@ S_make_method_obj(CFCClass *klass, const char *method_name) {
     const char *klass_name   = CFCClass_get_class_name(klass);
     const char *klass_cnick  = CFCClass_get_cnick(klass);
     CFCParcel  *klass_parcel = CFCClass_get_parcel(klass);
-    CFCParcel  *cf_parcel    = CFCParcel_clownfish_parcel();
 
     CFCType *return_type
-        = CFCType_new_object(CFCTYPE_INCREMENTED, cf_parcel, "Obj", 1);
+        = CFCType_new_object(CFCTYPE_INCREMENTED, klass_parcel, "Obj", 1);
     CFCType *self_type = CFCType_new_object(0, klass_parcel, klass_struct_sym, 1);
     CFCVariable *self_var = CFCVariable_new(NULL, NULL, NULL, NULL, "self",
                                             self_type, false);
@@ -128,7 +127,7 @@ S_make_method_obj(CFCClass *klass, const char *method_name) {
         CFCParamList_add_param(param_list, self_var, NULL);
     }
     else if (strcmp(method_name, "Load") == 0) {
-        CFCType *dump_type = CFCType_new_object(0, cf_parcel, "Obj", 1);
+        CFCType *dump_type = CFCType_new_object(0, klass_parcel, "Obj", 1);
         CFCVariable *dump_var = CFCVariable_new(NULL, NULL, NULL, NULL, "dump",
                                                 dump_type, false);
         param_list = CFCParamList_new(false);

http://git-wip-us.apache.org/repos/asf/lucy/blob/cecd5242/clownfish/compiler/src/CFCParcel.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParcel.c b/clownfish/compiler/src/CFCParcel.c
index 9949039..1cfe17e 100644
--- a/clownfish/compiler/src/CFCParcel.c
+++ b/clownfish/compiler/src/CFCParcel.c
@@ -289,19 +289,6 @@ CFCParcel_default_parcel(void) {
     return default_parcel;
 }
 
-CFCParcel*
-CFCParcel_clownfish_parcel(void) {
-    CFCParcel *parcel = CFCParcel_fetch("Lucy");
-    if (!parcel) {
-        CFCVersion *version = CFCVersion_new("v0.3.0");
-        parcel = CFCParcel_new("Lucy", "Lucy", version);
-        CFCParcel_register(parcel);
-        CFCBase_decref((CFCBase*)version);
-        CFCBase_decref((CFCBase*)parcel);
-    }
-    return parcel;
-}
-
 int
 CFCParcel_equals(CFCParcel *self, CFCParcel *other) {
     if (strcmp(self->name, other->name)) { return false; }

http://git-wip-us.apache.org/repos/asf/lucy/blob/cecd5242/clownfish/compiler/src/CFCParcel.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCParcel.h b/clownfish/compiler/src/CFCParcel.h
index 94b57ae..9ea3a4a 100644
--- a/clownfish/compiler/src/CFCParcel.h
+++ b/clownfish/compiler/src/CFCParcel.h
@@ -77,13 +77,6 @@ CFCParcel_destroy(CFCParcel *self);
 CFCParcel*
 CFCParcel_default_parcel(void);
 
-/** Return the Parcel under which Obj, CharBuf, VArray, Hash, etc. live.  At
- * some point in the future, these core object types may move to the
- * "Clownfish" CFC" Parcel, but for now they are within "Lucy".
- */
-CFCParcel*
-CFCParcel_clownfish_parcel(void);
-
 int
 CFCParcel_equals(CFCParcel *self, CFCParcel *other);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/cecd5242/clownfish/compiler/src/CFCType.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCType.h b/clownfish/compiler/src/CFCType.h
index eebb2bb..5c1354b 100644
--- a/clownfish/compiler/src/CFCType.h
+++ b/clownfish/compiler/src/CFCType.h
@@ -202,6 +202,9 @@ CFCType_get_vtable_var(CFCType *self);
 int
 CFCType_get_indirection(CFCType *self);
 
+/* Return the parcel in which the Type is used. Note that for class types,
+ * this is not neccessarily the parcel where class is defined.
+ */
 struct CFCParcel*
 CFCType_get_parcel(CFCType *self);
 


[lucy-commits] [26/26] git commit: refs/heads/separate-clownfish-wip2 - Rework Clownfish test harness

Posted by nw...@apache.org.
Rework Clownfish test harness

This commit corrects some bad design decisions I made when I
reimplemented the Clownfish test harness.

The new TestBatch class that the test modules inherit from contains only
a single abstract method "Run". All the other functionality is moved to
a new class TestBatchRunner. An instance of TestBatchRunner is passed to
the "Run" method of TestBatch. This means that TestBatch doesn't have to
care about TestFormatters.

The old TestRunner is renamed to TestSuiteRunner. There's a new class
TestSuite that manages a collection of TestBatches.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/3da6ebd3
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/3da6ebd3
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/3da6ebd3

Branch: refs/heads/separate-clownfish-wip2
Commit: 3da6ebd3f6fad0db4ee79db07b630a56c7dcf667
Parents: cb13877
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue May 28 00:33:52 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu May 30 22:32:00 2013 +0200

----------------------------------------------------------------------
 c/t/test_lucy.c                                    |   18 +-
 core/Clownfish/Test.c                              |   97 +----
 core/Clownfish/Test.cfh                            |   22 +-
 core/Clownfish/Test/TestByteBuf.c                  |   88 ++---
 core/Clownfish/Test/TestByteBuf.cfh                |    7 +-
 core/Clownfish/Test/TestCharBuf.c                  |  202 +++++-----
 core/Clownfish/Test/TestCharBuf.cfh                |    7 +-
 core/Clownfish/Test/TestErr.c                      |   22 +-
 core/Clownfish/Test/TestErr.cfh                    |    7 +-
 core/Clownfish/Test/TestHash.c                     |  100 +++---
 core/Clownfish/Test/TestHash.cfh                   |    7 +-
 core/Clownfish/Test/TestLockFreeRegistry.c         |   32 +-
 core/Clownfish/Test/TestLockFreeRegistry.cfh       |    7 +-
 core/Clownfish/Test/TestNum.c                      |  156 ++++----
 core/Clownfish/Test/TestNum.cfh                    |    7 +-
 core/Clownfish/Test/TestObj.c                      |   88 ++---
 core/Clownfish/Test/TestObj.cfh                    |    7 +-
 core/Clownfish/Test/TestVArray.c                   |  150 ++++----
 core/Clownfish/Test/TestVArray.cfh                 |    7 +-
 core/Clownfish/Test/Util/TestAtomic.c              |   32 +-
 core/Clownfish/Test/Util/TestAtomic.cfh            |    7 +-
 core/Clownfish/Test/Util/TestMemory.c              |   46 +--
 core/Clownfish/Test/Util/TestMemory.cfh            |    7 +-
 core/Clownfish/Test/Util/TestNumberUtils.c         |  116 +++---
 core/Clownfish/Test/Util/TestNumberUtils.cfh       |    7 +-
 core/Clownfish/Test/Util/TestStringHelper.c        |  140 ++++----
 core/Clownfish/Test/Util/TestStringHelper.cfh      |    7 +-
 core/Clownfish/TestHarness/TestBatch.c             |  293 --------------
 core/Clownfish/TestHarness/TestBatch.cfh           |   98 +-----
 core/Clownfish/TestHarness/TestBatchRunner.c       |  308 +++++++++++++++
 core/Clownfish/TestHarness/TestBatchRunner.cfh     |  135 +++++++
 core/Clownfish/TestHarness/TestFormatter.c         |   37 +-
 core/Clownfish/TestHarness/TestFormatter.cfh       |   38 +-
 core/Clownfish/TestHarness/TestRunner.c            |   93 -----
 core/Clownfish/TestHarness/TestRunner.cfh          |   77 ----
 core/Clownfish/TestHarness/TestSuite.c             |  109 +++++
 core/Clownfish/TestHarness/TestSuite.cfh           |   43 ++
 core/Clownfish/TestHarness/TestSuiteRunner.c       |   97 +++++
 core/Clownfish/TestHarness/TestSuiteRunner.cfh     |   76 ++++
 core/Lucy/Test.c                                   |  192 ++++------
 core/Lucy/Test.cfh                                 |   22 +-
 core/Lucy/Test/Analysis/TestAnalyzer.c             |   22 +-
 core/Lucy/Test/Analysis/TestAnalyzer.cfh           |    7 +-
 core/Lucy/Test/Analysis/TestCaseFolder.c           |   32 +-
 core/Lucy/Test/Analysis/TestCaseFolder.cfh         |    7 +-
 core/Lucy/Test/Analysis/TestNormalizer.c           |   34 +-
 core/Lucy/Test/Analysis/TestNormalizer.cfh         |    7 +-
 core/Lucy/Test/Analysis/TestPolyAnalyzer.c         |   53 ++--
 core/Lucy/Test/Analysis/TestPolyAnalyzer.cfh       |    7 +-
 core/Lucy/Test/Analysis/TestRegexTokenizer.c       |   33 +-
 core/Lucy/Test/Analysis/TestRegexTokenizer.cfh     |    7 +-
 core/Lucy/Test/Analysis/TestSnowballStemmer.c      |   32 +-
 core/Lucy/Test/Analysis/TestSnowballStemmer.cfh    |    7 +-
 core/Lucy/Test/Analysis/TestSnowballStopFilter.c   |   26 +-
 core/Lucy/Test/Analysis/TestSnowballStopFilter.cfh |    7 +-
 core/Lucy/Test/Analysis/TestStandardTokenizer.c    |   41 +--
 core/Lucy/Test/Analysis/TestStandardTokenizer.cfh  |    7 +-
 core/Lucy/Test/Highlight/TestHeatMap.c             |   50 +--
 core/Lucy/Test/Highlight/TestHeatMap.cfh           |    7 +-
 core/Lucy/Test/Highlight/TestHighlighter.c         |  114 +++---
 core/Lucy/Test/Highlight/TestHighlighter.cfh       |    7 +-
 core/Lucy/Test/Index/TestDocWriter.c               |   18 +-
 core/Lucy/Test/Index/TestDocWriter.cfh             |    7 +-
 core/Lucy/Test/Index/TestHighlightWriter.c         |   18 +-
 core/Lucy/Test/Index/TestHighlightWriter.cfh       |    7 +-
 core/Lucy/Test/Index/TestIndexManager.c            |   24 +-
 core/Lucy/Test/Index/TestIndexManager.cfh          |    7 +-
 core/Lucy/Test/Index/TestPolyReader.c              |   22 +-
 core/Lucy/Test/Index/TestPolyReader.cfh            |    7 +-
 core/Lucy/Test/Index/TestPostingListWriter.c       |   18 +-
 core/Lucy/Test/Index/TestPostingListWriter.cfh     |    7 +-
 core/Lucy/Test/Index/TestSegWriter.c               |   18 +-
 core/Lucy/Test/Index/TestSegWriter.cfh             |    7 +-
 core/Lucy/Test/Index/TestSegment.c                 |   82 ++--
 core/Lucy/Test/Index/TestSegment.cfh               |    7 +-
 core/Lucy/Test/Index/TestSnapshot.c                |   46 +--
 core/Lucy/Test/Index/TestSnapshot.cfh              |    7 +-
 core/Lucy/Test/Index/TestTermInfo.c                |   42 +--
 core/Lucy/Test/Index/TestTermInfo.cfh              |    7 +-
 core/Lucy/Test/Object/TestBitVector.c              |  140 ++++----
 core/Lucy/Test/Object/TestBitVector.cfh            |    7 +-
 core/Lucy/Test/Object/TestI32Array.c               |   28 +-
 core/Lucy/Test/Object/TestI32Array.cfh             |    7 +-
 core/Lucy/Test/Plan/TestBlobType.c                 |   24 +-
 core/Lucy/Test/Plan/TestBlobType.cfh               |    7 +-
 core/Lucy/Test/Plan/TestFieldMisc.c                |   46 +--
 core/Lucy/Test/Plan/TestFieldMisc.cfh              |    7 +-
 core/Lucy/Test/Plan/TestFieldType.c                |   42 +--
 core/Lucy/Test/Plan/TestFieldType.cfh              |    7 +-
 core/Lucy/Test/Plan/TestFullTextType.c             |   44 +--
 core/Lucy/Test/Plan/TestFullTextType.cfh           |    7 +-
 core/Lucy/Test/Plan/TestNumericType.c              |   44 +--
 core/Lucy/Test/Plan/TestNumericType.cfh            |    7 +-
 core/Lucy/Test/Search/TestLeafQuery.c              |   30 +-
 core/Lucy/Test/Search/TestLeafQuery.cfh            |    7 +-
 core/Lucy/Test/Search/TestMatchAllQuery.c          |   24 +-
 core/Lucy/Test/Search/TestMatchAllQuery.cfh        |    7 +-
 core/Lucy/Test/Search/TestNOTQuery.c               |   28 +-
 core/Lucy/Test/Search/TestNOTQuery.cfh             |    7 +-
 core/Lucy/Test/Search/TestNoMatchQuery.c           |   24 +-
 core/Lucy/Test/Search/TestNoMatchQuery.cfh         |    7 +-
 core/Lucy/Test/Search/TestPhraseQuery.c            |   22 +-
 core/Lucy/Test/Search/TestPhraseQuery.cfh          |    7 +-
 core/Lucy/Test/Search/TestPolyQuery.c              |   44 +--
 core/Lucy/Test/Search/TestPolyQuery.cfh            |   14 +-
 core/Lucy/Test/Search/TestQueryParserLogic.c       |   29 +-
 core/Lucy/Test/Search/TestQueryParserLogic.cfh     |    7 +-
 core/Lucy/Test/Search/TestQueryParserSyntax.c      |   41 +--
 core/Lucy/Test/Search/TestQueryParserSyntax.cfh    |    7 +-
 core/Lucy/Test/Search/TestRangeQuery.c             |   30 +-
 core/Lucy/Test/Search/TestRangeQuery.cfh           |    7 +-
 core/Lucy/Test/Search/TestReqOptQuery.c            |   28 +-
 core/Lucy/Test/Search/TestReqOptQuery.cfh          |    7 +-
 core/Lucy/Test/Search/TestSeriesMatcher.c          |   26 +-
 core/Lucy/Test/Search/TestSeriesMatcher.cfh        |    7 +-
 core/Lucy/Test/Search/TestSortSpec.c               |   60 ++--
 core/Lucy/Test/Search/TestSortSpec.cfh             |    7 +-
 core/Lucy/Test/Search/TestSpan.c                   |   32 +-
 core/Lucy/Test/Search/TestSpan.cfh                 |    7 +-
 core/Lucy/Test/Search/TestTermQuery.c              |   28 +-
 core/Lucy/Test/Search/TestTermQuery.cfh            |    7 +-
 core/Lucy/Test/Store/TestCompoundFileReader.c      |  140 ++++----
 core/Lucy/Test/Store/TestCompoundFileReader.cfh    |    7 +-
 core/Lucy/Test/Store/TestCompoundFileWriter.c      |   40 +--
 core/Lucy/Test/Store/TestCompoundFileWriter.cfh    |    7 +-
 core/Lucy/Test/Store/TestFSDirHandle.c             |   30 +-
 core/Lucy/Test/Store/TestFSDirHandle.cfh           |    7 +-
 core/Lucy/Test/Store/TestFSFileHandle.c            |  128 +++----
 core/Lucy/Test/Store/TestFSFileHandle.cfh          |    7 +-
 core/Lucy/Test/Store/TestFSFolder.c                |   70 ++--
 core/Lucy/Test/Store/TestFSFolder.cfh              |    7 +-
 core/Lucy/Test/Store/TestFileHandle.c              |   21 +-
 core/Lucy/Test/Store/TestFileHandle.cfh            |    7 +-
 core/Lucy/Test/Store/TestFolder.c                  |  222 +++++------
 core/Lucy/Test/Store/TestFolder.cfh                |    7 +-
 core/Lucy/Test/Store/TestFolderCommon.c            |  250 ++++++------
 core/Lucy/Test/Store/TestFolderCommon.cfh          |    2 +-
 core/Lucy/Test/Store/TestIOChunks.c                |   40 +--
 core/Lucy/Test/Store/TestIOChunks.cfh              |    7 +-
 core/Lucy/Test/Store/TestIOPrimitives.c            |   96 +++---
 core/Lucy/Test/Store/TestIOPrimitives.cfh          |    7 +-
 core/Lucy/Test/Store/TestInStream.c                |  106 +++---
 core/Lucy/Test/Store/TestInStream.cfh              |    7 +-
 core/Lucy/Test/Store/TestRAMDirHandle.c            |   32 +-
 core/Lucy/Test/Store/TestRAMDirHandle.cfh          |    7 +-
 core/Lucy/Test/Store/TestRAMFileHandle.c           |  100 +++---
 core/Lucy/Test/Store/TestRAMFileHandle.cfh         |    7 +-
 core/Lucy/Test/Store/TestRAMFolder.c               |  256 ++++++------
 core/Lucy/Test/Store/TestRAMFolder.cfh             |    7 +-
 core/Lucy/Test/TestSchema.c                        |   32 +-
 core/Lucy/Test/TestSchema.cfh                      |    7 +-
 core/Lucy/Test/TestUtils.c                         |   13 +-
 core/Lucy/Test/TestUtils.cfh                       |    2 +-
 core/Lucy/Test/Util/TestIndexFileNames.c           |   44 +--
 core/Lucy/Test/Util/TestIndexFileNames.cfh         |    7 +-
 core/Lucy/Test/Util/TestJson.c                     |  174 ++++-----
 core/Lucy/Test/Util/TestJson.cfh                   |    7 +-
 core/Lucy/Test/Util/TestMemoryPool.c               |   25 +-
 core/Lucy/Test/Util/TestMemoryPool.cfh             |    7 +-
 core/Lucy/Test/Util/TestPriorityQueue.c            |   66 ++--
 core/Lucy/Test/Util/TestPriorityQueue.cfh          |    7 +-
 perl/buildlib/Lucy/Build/Binding/Misc.pm           |    8 +-
 162 files changed, 3152 insertions(+), 3708 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/c/t/test_lucy.c
----------------------------------------------------------------------
diff --git a/c/t/test_lucy.c b/c/t/test_lucy.c
index 808d0f7..f0018b1 100644
--- a/c/t/test_lucy.c
+++ b/c/t/test_lucy.c
@@ -17,22 +17,30 @@
 #include <stdlib.h>
 
 #include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestSuite.h"
 #include "Clownfish/Test.h"
 #include "Lucy/Test.h"
 
 int
 main() {
-    cfish_TestFormatterCF *formatter;
+    cfish_TestFormatter *formatter;
+    cfish_TestSuite     *cfish_suite;
+    cfish_TestSuite     *lucy_suite;
     bool success = true;
 
     testcfish_bootstrap_parcel();
     testlucy_bootstrap_parcel();
 
-    formatter = cfish_TestFormatterCF_new();
-    success &= testcfish_Test_run_all_batches((cfish_TestFormatter*)formatter);
-    success &= testlucy_Test_run_all_batches((cfish_TestFormatter*)formatter);
-    CFISH_DECREF(formatter);
+    formatter   = (cfish_TestFormatter*)cfish_TestFormatterCF_new();
+    cfish_suite = testcfish_Test_create_test_suite();
+    lucy_suite  = testlucy_Test_create_test_suite();
+
+    success &= Cfish_TestSuite_Run_All_Batches(cfish_suite, formatter);
+    success &= Cfish_TestSuite_Run_All_Batches(lucy_suite, formatter);
 
+    CFISH_DECREF(formatter);
+    CFISH_DECREF(cfish_suite);
+    CFISH_DECREF(lucy_suite);
     return success ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test.c b/core/Clownfish/Test.c
index 4d2a9fc..546af45 100644
--- a/core/Clownfish/Test.c
+++ b/core/Clownfish/Test.c
@@ -14,19 +14,13 @@
  * limitations under the License.
  */
 
-#include <stdio.h>
-
-#define CHY_USE_SHORT_NAMES
 #define CFISH_USE_SHORT_NAMES
 #define TESTCFISH_USE_SHORT_NAMES
 
 #include "Clownfish/Test.h"
 
-#include "Clownfish/Err.h"
 #include "Clownfish/TestHarness/TestBatch.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
-#include "Clownfish/TestHarness/TestRunner.h"
-#include "Clownfish/VArray.h"
+#include "Clownfish/TestHarness/TestSuite.h"
 
 #include "Clownfish/Test/TestByteBuf.h"
 #include "Clownfish/Test/TestCharBuf.h"
@@ -41,77 +35,24 @@
 #include "Clownfish/Test/Util/TestNumberUtils.h"
 #include "Clownfish/Test/Util/TestStringHelper.h"
 
-static void
-S_unbuffer_stdout();
-
-static VArray*
-S_all_test_batches(TestFormatter *formatter) {
-    VArray *batches = VA_new(0);
-
-    VA_Push(batches, (Obj*)TestVArray_new(formatter));
-    VA_Push(batches, (Obj*)TestHash_new(formatter));
-    VA_Push(batches, (Obj*)TestObj_new(formatter));
-    VA_Push(batches, (Obj*)TestErr_new(formatter));
-    VA_Push(batches, (Obj*)TestBB_new(formatter));
-    VA_Push(batches, (Obj*)TestCB_new(formatter));
-    VA_Push(batches, (Obj*)TestNumUtil_new(formatter));
-    VA_Push(batches, (Obj*)TestNum_new(formatter));
-    VA_Push(batches, (Obj*)TestStrHelp_new(formatter));
-    VA_Push(batches, (Obj*)TestAtomic_new(formatter));
-    VA_Push(batches, (Obj*)TestLFReg_new(formatter));
-    VA_Push(batches, (Obj*)TestMemory_new(formatter));
-
-    return batches;
-}
-
-bool
-Test_run_batch(CharBuf *class_name, TestFormatter *formatter) {
-    S_unbuffer_stdout();
-
-    VArray   *batches = S_all_test_batches(formatter);
-    uint32_t  size    = VA_Get_Size(batches);
-
-    for (uint32_t i = 0; i < size; ++i) {
-        TestBatch *batch = (TestBatch*)VA_Fetch(batches, i);
-
-        if (CB_Equals(TestBatch_Get_Class_Name(batch), (Obj*)class_name)) {
-            bool result = TestBatch_Run(batch);
-            DECREF(batches);
-            return result;
-        }
-    }
-
-    DECREF(batches);
-    THROW(ERR, "Couldn't find test class '%o'", class_name);
-    UNREACHABLE_RETURN(bool);
-}
-
-bool
-Test_run_all_batches(TestFormatter *formatter) {
-    S_unbuffer_stdout();
-
-    TestRunner *runner  = TestRunner_new(formatter);
-    VArray     *batches = S_all_test_batches(formatter);
-    uint32_t    size    = VA_Get_Size(batches);
-
-    for (uint32_t i = 0; i < size; ++i) {
-        TestBatch *batch = (TestBatch*)VA_Fetch(batches, i);
-        TestRunner_Run_Batch(runner, batch);
-    }
-
-    bool result = TestRunner_Finish(runner);
-
-    DECREF(runner);
-    DECREF(batches);
-    return result;
-}
-
-static void
-S_unbuffer_stdout() {
-    int check_val = setvbuf(stdout, NULL, _IONBF, 0);
-    if (check_val != 0) {
-        fprintf(stderr, "Failed when trying to unbuffer stdout\n");
-    }
+TestSuite*
+Test_create_test_suite() {
+    TestSuite *suite = TestSuite_new();
+
+    TestSuite_Add_Batch(suite, (TestBatch*)TestVArray_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestHash_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestObj_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestErr_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestBB_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestCB_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestNumUtil_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestNum_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestStrHelp_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestAtomic_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestLFReg_new());
+    TestSuite_Add_Batch(suite, (TestBatch*)TestMemory_new());
+
+    return suite;
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test.cfh b/core/Clownfish/Test.cfh
index 4ceb429..68dc8bc 100644
--- a/core/Clownfish/Test.cfh
+++ b/core/Clownfish/Test.cfh
@@ -16,27 +16,11 @@
 
 parcel TestClownfish;
 
-/** Testing framework.
+/** Clownfish test suite.
  */
 inert class Clownfish::Test {
-    inert bool
-    run_batch(CharBuf *class_name, TestFormatter *formatter);
-
-    inert bool
-    run_all_batches(TestFormatter *formatter);
+    inert incremented TestSuite*
+    create_test_suite();
 }
 
-__C__
-#ifdef TESTCFISH_USE_SHORT_NAMES
-  #define TEST_TRUE                    cfish_TestBatch_test_true
-  #define TEST_FALSE                   cfish_TestBatch_test_false
-  #define TEST_INT_EQ                  cfish_TestBatch_test_int_equals
-  #define TEST_FLOAT_EQ                cfish_TestBatch_test_float_equals
-  #define TEST_STR_EQ                  cfish_TestBatch_test_string_equals
-  #define PASS                         cfish_TestBatch_pass
-  #define FAIL                         cfish_TestBatch_fail
-  #define SKIP                         cfish_TestBatch_skip
-#endif
-__END_C__
-
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestByteBuf.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestByteBuf.c b/core/Clownfish/Test/TestByteBuf.c
index 98da9c3..1fe8a2b 100644
--- a/core/Clownfish/Test/TestByteBuf.c
+++ b/core/Clownfish/Test/TestByteBuf.c
@@ -23,45 +23,39 @@
 
 #include "Clownfish/ByteBuf.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VTable.h"
 
 TestByteBuf*
-TestBB_new(TestFormatter *formatter) {
-    TestByteBuf *self = (TestByteBuf*)VTable_Make_Obj(TESTBYTEBUF);
-    return TestBB_init(self, formatter);
-}
-
-TestByteBuf*
-TestBB_init(TestByteBuf *self, TestFormatter *formatter) {
-    return (TestByteBuf*)TestBatch_init((TestBatch*)self, 22, formatter);
+TestBB_new() {
+    return (TestByteBuf*)VTable_Make_Obj(TESTBYTEBUF);
 }
 
 static void
-test_Equals(TestBatch *batch) {
+test_Equals(TestBatchRunner *runner) {
     ByteBuf *wanted = BB_new_bytes("foo", 4); // Include terminating NULL.
     ByteBuf *got    = BB_new_bytes("foo", 4);
 
-    TEST_TRUE(batch, BB_Equals(wanted, (Obj*)got), "Equals");
-    TEST_INT_EQ(batch, BB_Hash_Sum(got), BB_Hash_Sum(wanted), "Hash_Sum");
+    TEST_TRUE(runner, BB_Equals(wanted, (Obj*)got), "Equals");
+    TEST_INT_EQ(runner, BB_Hash_Sum(got), BB_Hash_Sum(wanted), "Hash_Sum");
 
-    TEST_TRUE(batch, BB_Equals_Bytes(got, "foo", 4), "Equals_Bytes");
-    TEST_FALSE(batch, BB_Equals_Bytes(got, "foo", 3),
+    TEST_TRUE(runner, BB_Equals_Bytes(got, "foo", 4), "Equals_Bytes");
+    TEST_FALSE(runner, BB_Equals_Bytes(got, "foo", 3),
                "Equals_Bytes spoiled by different size");
-    TEST_FALSE(batch, BB_Equals_Bytes(got, "bar", 4),
+    TEST_FALSE(runner, BB_Equals_Bytes(got, "bar", 4),
                "Equals_Bytes spoiled by different content");
 
     BB_Set_Size(got, 3);
-    TEST_FALSE(batch, BB_Equals(wanted, (Obj*)got),
+    TEST_FALSE(runner, BB_Equals(wanted, (Obj*)got),
                "Different size spoils Equals");
-    TEST_FALSE(batch, BB_Hash_Sum(got) == BB_Hash_Sum(wanted),
+    TEST_FALSE(runner, BB_Hash_Sum(got) == BB_Hash_Sum(wanted),
                "Different size spoils Hash_Sum (probably -- at least this one)");
 
     BB_Mimic_Bytes(got, "bar", 4);
-    TEST_INT_EQ(batch, BB_Get_Size(wanted), BB_Get_Size(got),
+    TEST_INT_EQ(runner, BB_Get_Size(wanted), BB_Get_Size(got),
                 "same length");
-    TEST_FALSE(batch, BB_Equals(wanted, (Obj*)got),
+    TEST_FALSE(runner, BB_Equals(wanted, (Obj*)got),
                "Different content spoils Equals");
 
     DECREF(got);
@@ -69,41 +63,41 @@ test_Equals(TestBatch *batch) {
 }
 
 static void
-test_Grow(TestBatch *batch) {
+test_Grow(TestBatchRunner *runner) {
     ByteBuf *bb = BB_new(1);
-    TEST_INT_EQ(batch, BB_Get_Capacity(bb), 8,
+    TEST_INT_EQ(runner, BB_Get_Capacity(bb), 8,
                 "Allocate in 8-byte increments");
     BB_Grow(bb, 9);
-    TEST_INT_EQ(batch, BB_Get_Capacity(bb), 16,
+    TEST_INT_EQ(runner, BB_Get_Capacity(bb), 16,
                 "Grow in 8-byte increments");
     DECREF(bb);
 }
 
 static void
-test_Clone(TestBatch *batch) {
+test_Clone(TestBatchRunner *runner) {
     ByteBuf *bb = BB_new_bytes("foo", 3);
     ByteBuf *twin = BB_Clone(bb);
-    TEST_TRUE(batch, BB_Equals(bb, (Obj*)twin), "Clone");
+    TEST_TRUE(runner, BB_Equals(bb, (Obj*)twin), "Clone");
     DECREF(bb);
     DECREF(twin);
 }
 
 static void
-test_compare(TestBatch *batch) {
+test_compare(TestBatchRunner *runner) {
     ByteBuf *a = BB_new_bytes("foo\0a", 5);
     ByteBuf *b = BB_new_bytes("foo\0b", 5);
 
     BB_Set_Size(a, 4);
     BB_Set_Size(b, 4);
-    TEST_INT_EQ(batch, BB_compare(&a, &b), 0,
+    TEST_INT_EQ(runner, BB_compare(&a, &b), 0,
                 "BB_compare returns 0 for equal ByteBufs");
 
     BB_Set_Size(a, 3);
-    TEST_TRUE(batch, BB_compare(&a, &b) < 0, "shorter ByteBuf sorts first");
+    TEST_TRUE(runner, BB_compare(&a, &b) < 0, "shorter ByteBuf sorts first");
 
     BB_Set_Size(a, 5);
     BB_Set_Size(b, 5);
-    TEST_TRUE(batch, BB_compare(&a, &b) < 0,
+    TEST_TRUE(runner, BB_compare(&a, &b) < 0,
               "NULL doesn't interfere with BB_compare");
 
     DECREF(a);
@@ -111,37 +105,37 @@ test_compare(TestBatch *batch) {
 }
 
 static void
-test_Mimic(TestBatch *batch) {
+test_Mimic(TestBatchRunner *runner) {
     ByteBuf *a = BB_new_bytes("foo", 3);
     ByteBuf *b = BB_new(0);
 
     BB_Mimic(b, (Obj*)a);
-    TEST_TRUE(batch, BB_Equals(a, (Obj*)b), "Mimic");
+    TEST_TRUE(runner, BB_Equals(a, (Obj*)b), "Mimic");
 
     BB_Mimic_Bytes(a, "bar", 4);
-    TEST_TRUE(batch, strcmp(BB_Get_Buf(a), "bar") == 0,
+    TEST_TRUE(runner, strcmp(BB_Get_Buf(a), "bar") == 0,
               "Mimic_Bytes content");
-    TEST_INT_EQ(batch, BB_Get_Size(a), 4, "Mimic_Bytes size");
+    TEST_INT_EQ(runner, BB_Get_Size(a), 4, "Mimic_Bytes size");
 
     BB_Mimic(b, (Obj*)a);
-    TEST_TRUE(batch, BB_Equals(a, (Obj*)b), "Mimic");
+    TEST_TRUE(runner, BB_Equals(a, (Obj*)b), "Mimic");
 
     DECREF(a);
     DECREF(b);
 }
 
 static void
-test_Cat(TestBatch *batch) {
+test_Cat(TestBatchRunner *runner) {
     ByteBuf *wanted  = BB_new_bytes("foobar", 6);
     ByteBuf *got     = BB_new_bytes("foo", 3);
     ByteBuf *scratch = BB_new_bytes("bar", 3);
 
     BB_Cat(got, scratch);
-    TEST_TRUE(batch, BB_Equals(wanted, (Obj*)got), "Cat");
+    TEST_TRUE(runner, BB_Equals(wanted, (Obj*)got), "Cat");
 
     BB_Mimic_Bytes(wanted, "foobarbaz", 9);
     BB_Cat_Bytes(got, "baz", 3);
-    TEST_TRUE(batch, BB_Equals(wanted, (Obj*)got), "Cat_Bytes");
+    TEST_TRUE(runner, BB_Equals(wanted, (Obj*)got), "Cat_Bytes");
 
     DECREF(scratch);
     DECREF(got);
@@ -149,25 +143,25 @@ test_Cat(TestBatch *batch) {
 }
 
 static void
-test_serialization(TestBatch *batch) {
+test_serialization(TestBatchRunner *runner) {
     ByteBuf *wanted = BB_new_bytes("foobar", 6);
     ByteBuf *got    = (ByteBuf*)TestUtils_freeze_thaw((Obj*)wanted);
-    TEST_TRUE(batch, got && BB_Equals(wanted, (Obj*)got),
+    TEST_TRUE(runner, got && BB_Equals(wanted, (Obj*)got),
               "Serialization round trip");
     DECREF(wanted);
     DECREF(got);
 }
 
 void
-TestBB_run_tests(TestByteBuf *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_Equals(batch);
-    test_Grow(batch);
-    test_Clone(batch);
-    test_compare(batch);
-    test_Mimic(batch);
-    test_Cat(batch);
-    test_serialization(batch);
+TestBB_run(TestByteBuf *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 22);
+    test_Equals(runner);
+    test_Grow(runner);
+    test_Clone(runner);
+    test_compare(runner);
+    test_Mimic(runner);
+    test_Cat(runner);
+    test_serialization(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestByteBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestByteBuf.cfh b/core/Clownfish/Test/TestByteBuf.cfh
index 6819191..3335c95 100644
--- a/core/Clownfish/Test/TestByteBuf.cfh
+++ b/core/Clownfish/Test/TestByteBuf.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::TestByteBuf cnick TestBB
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestByteBuf*
-    new(TestFormatter *formatter);
-
-    inert TestByteBuf*
-    init(TestByteBuf *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestByteBuf *self);
+    Run(TestByteBuf *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestCharBuf.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestCharBuf.c b/core/Clownfish/Test/TestCharBuf.c
index bc8a348..a75ce65 100644
--- a/core/Clownfish/Test/TestCharBuf.c
+++ b/core/Clownfish/Test/TestCharBuf.c
@@ -26,7 +26,7 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Num.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VTable.h"
 
@@ -34,14 +34,8 @@ static char smiley[] = { (char)0xE2, (char)0x98, (char)0xBA, 0 };
 static uint32_t smiley_len = 3;
 
 TestCharBuf*
-TestCB_new(TestFormatter *formatter) {
-    TestCharBuf *self = (TestCharBuf*)VTable_Make_Obj(TESTCHARBUF);
-    return TestCB_init(self, formatter);
-}
-
-TestCharBuf*
-TestCB_init(TestCharBuf *self, TestFormatter *formatter) {
-    return (TestCharBuf*)TestBatch_init((TestBatch*)self, 55, formatter);
+TestCB_new() {
+    return (TestCharBuf*)VTable_Make_Obj(TESTCHARBUF);
 }
 
 static CharBuf*
@@ -50,74 +44,74 @@ S_get_cb(const char *string) {
 }
 
 static void
-test_Cat(TestBatch *batch) {
+test_Cat(TestBatchRunner *runner) {
     CharBuf *wanted = CB_newf("a%s", smiley);
     CharBuf *got    = S_get_cb("");
 
     CB_Cat(got, wanted);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Cat");
     DECREF(got);
 
     got = S_get_cb("a");
     CB_Cat_Char(got, 0x263A);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Char");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Cat_Char");
     DECREF(got);
 
     got = S_get_cb("a");
     CB_Cat_Str(got, smiley, smiley_len);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Str");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Cat_Str");
     DECREF(got);
 
     got = S_get_cb("a");
     CB_Cat_Trusted_Str(got, smiley, smiley_len);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Trusted_Str");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Cat_Trusted_Str");
     DECREF(got);
 
     DECREF(wanted);
 }
 
 static void
-test_Mimic_and_Clone(TestBatch *batch) {
+test_Mimic_and_Clone(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo");
     CharBuf *got    = S_get_cb("bar");
 
     CB_Mimic(got, (Obj*)wanted);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Mimic");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Mimic");
     DECREF(got);
 
     got = S_get_cb("bar");
     CB_Mimic_Str(got, "foo", 3);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Mimic_Str");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Mimic_Str");
     DECREF(got);
 
     got = CB_Clone(wanted);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Clone");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Clone");
     DECREF(got);
 
     DECREF(wanted);
 }
 
 static void
-test_Find(TestBatch *batch) {
+test_Find(TestBatchRunner *runner) {
     CharBuf *string = CB_new(10);
     CharBuf *substring = S_get_cb("foo");
 
-    TEST_TRUE(batch, CB_Find(string, substring) == -1, "Not in empty string");
+    TEST_TRUE(runner, CB_Find(string, substring) == -1, "Not in empty string");
     CB_setf(string, "foo");
-    TEST_TRUE(batch, CB_Find(string, substring) == 0, "Find complete string");
+    TEST_TRUE(runner, CB_Find(string, substring) == 0, "Find complete string");
     CB_setf(string, "afoo");
-    TEST_TRUE(batch, CB_Find(string, substring) == 1, "Find after first");
+    TEST_TRUE(runner, CB_Find(string, substring) == 1, "Find after first");
     CB_Set_Size(string, 3);
-    TEST_TRUE(batch, CB_Find(string, substring) == -1, "Don't overrun");
+    TEST_TRUE(runner, CB_Find(string, substring) == -1, "Don't overrun");
     CB_setf(string, "afood");
-    TEST_TRUE(batch, CB_Find(string, substring) == 1, "Find in middle");
+    TEST_TRUE(runner, CB_Find(string, substring) == 1, "Find in middle");
 
     DECREF(substring);
     DECREF(string);
 }
 
 static void
-test_Code_Point_At_and_From(TestBatch *batch) {
+test_Code_Point_At_and_From(TestBatchRunner *runner) {
     uint32_t code_points[] = { 'a', 0x263A, 0x263A, 'b', 0x263A, 'c' };
     uint32_t num_code_points = sizeof(code_points) / sizeof(uint32_t);
     CharBuf *string = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
@@ -125,9 +119,9 @@ test_Code_Point_At_and_From(TestBatch *batch) {
 
     for (i = 0; i < num_code_points; i++) {
         uint32_t from = num_code_points - i - 1;
-        TEST_INT_EQ(batch, CB_Code_Point_At(string, i), code_points[i],
+        TEST_INT_EQ(runner, CB_Code_Point_At(string, i), code_points[i],
                     "Code_Point_At %ld", (long)i);
-        TEST_INT_EQ(batch, CB_Code_Point_At(string, from),
+        TEST_INT_EQ(runner, CB_Code_Point_At(string, from),
                     code_points[from], "Code_Point_From %ld", (long)from);
     }
 
@@ -135,49 +129,49 @@ test_Code_Point_At_and_From(TestBatch *batch) {
 }
 
 static void
-test_SubString(TestBatch *batch) {
+test_SubString(TestBatchRunner *runner) {
     CharBuf *string = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
     CharBuf *wanted = CB_newf("%sb%s", smiley, smiley);
     CharBuf *got = CB_SubString(string, 2, 3);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "SubString");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "SubString");
     DECREF(wanted);
     DECREF(got);
     DECREF(string);
 }
 
 static void
-test_Nip_and_Chop(TestBatch *batch) {
+test_Nip_and_Chop(TestBatchRunner *runner) {
     CharBuf *wanted;
     CharBuf *got;
 
     wanted = CB_newf("%sb%sc", smiley, smiley);
     got    = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
     CB_Nip(got, 2);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Nip");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Nip");
     DECREF(wanted);
     DECREF(got);
 
     wanted = CB_newf("a%s%s", smiley, smiley);
     got    = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
     CB_Chop(got, 3);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Chop");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Chop");
     DECREF(wanted);
     DECREF(got);
 }
 
 
 static void
-test_Truncate(TestBatch *batch) {
+test_Truncate(TestBatchRunner *runner) {
     CharBuf *wanted = CB_newf("a%s", smiley, smiley);
     CharBuf *got    = CB_newf("a%s%sb%sc", smiley, smiley, smiley);
     CB_Truncate(got, 2);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Truncate");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "Truncate");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_Trim(TestBatch *batch) {
+test_Trim(TestBatchRunner *runner) {
     uint32_t spaces[] = {
         ' ',    '\t',   '\r',   '\n',   0x000B, 0x000C, 0x000D, 0x0085,
         0x00A0, 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004,
@@ -193,13 +187,13 @@ test_Trim(TestBatch *batch) {
     CB_Cat_Char(got, 0x263A);
     for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
 
-    TEST_TRUE(batch, CB_Trim_Top(got), "Trim_Top returns true on success");
-    TEST_FALSE(batch, CB_Trim_Top(got),
+    TEST_TRUE(runner, CB_Trim_Top(got), "Trim_Top returns true on success");
+    TEST_FALSE(runner, CB_Trim_Top(got),
                "Trim_Top returns false on failure");
-    TEST_TRUE(batch, CB_Trim_Tail(got), "Trim_Tail returns true on success");
-    TEST_FALSE(batch, CB_Trim_Tail(got),
+    TEST_TRUE(runner, CB_Trim_Tail(got), "Trim_Tail returns true on success");
+    TEST_FALSE(runner, CB_Trim_Tail(got),
                "Trim_Tail returns false on failure");
-    TEST_TRUE(batch, CB_Equals_Str(got, smiley, smiley_len),
+    TEST_TRUE(runner, CB_Equals_Str(got, smiley, smiley_len),
               "Trim_Top and Trim_Tail worked");
 
     // Build the spacey smiley again.
@@ -208,168 +202,168 @@ test_Trim(TestBatch *batch) {
     CB_Cat_Char(got, 0x263A);
     for (i = 0; i < num_spaces; i++) { CB_Cat_Char(got, spaces[i]); }
 
-    TEST_TRUE(batch, CB_Trim(got), "Trim returns true on success");
-    TEST_FALSE(batch, CB_Trim(got), "Trim returns false on failure");
-    TEST_TRUE(batch, CB_Equals_Str(got, smiley, smiley_len),
+    TEST_TRUE(runner, CB_Trim(got), "Trim returns true on success");
+    TEST_FALSE(runner, CB_Trim(got), "Trim returns false on failure");
+    TEST_TRUE(runner, CB_Equals_Str(got, smiley, smiley_len),
               "Trim worked");
 
     DECREF(got);
 }
 
 static void
-test_To_F64(TestBatch *batch) {
+test_To_F64(TestBatchRunner *runner) {
     CharBuf *charbuf = S_get_cb("1.5");
     double difference = 1.5 - CB_To_F64(charbuf);
     if (difference < 0) { difference = 0 - difference; }
-    TEST_TRUE(batch, difference < 0.001, "To_F64");
+    TEST_TRUE(runner, difference < 0.001, "To_F64");
 
     CB_setf(charbuf, "-1.5");
     difference = 1.5 + CB_To_F64(charbuf);
     if (difference < 0) { difference = 0 - difference; }
-    TEST_TRUE(batch, difference < 0.001, "To_F64 negative");
+    TEST_TRUE(runner, difference < 0.001, "To_F64 negative");
 
     CB_setf(charbuf, "1.59");
     double value_full = CB_To_F64(charbuf);
     CB_Set_Size(charbuf, 3);
     double value_short = CB_To_F64(charbuf);
-    TEST_TRUE(batch, value_short < value_full,
+    TEST_TRUE(runner, value_short < value_full,
               "TO_F64 doesn't run past end of string");
 
     DECREF(charbuf);
 }
 
 static void
-test_To_I64(TestBatch *batch) {
+test_To_I64(TestBatchRunner *runner) {
     CharBuf *charbuf = S_get_cb("10");
-    TEST_TRUE(batch, CB_To_I64(charbuf) == 10, "To_I64");
+    TEST_TRUE(runner, CB_To_I64(charbuf) == 10, "To_I64");
     CB_setf(charbuf, "-10");
-    TEST_TRUE(batch, CB_To_I64(charbuf) == -10, "To_I64 negative");
+    TEST_TRUE(runner, CB_To_I64(charbuf) == -10, "To_I64 negative");
     DECREF(charbuf);
 }
 
 
 static void
-test_vcatf_s(TestBatch *batch) {
+test_vcatf_s(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar bizzle baz");
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %s baz", "bizzle");
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%s");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%s");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_null_string(TestBatch *batch) {
+test_vcatf_null_string(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar [NULL] baz");
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %s baz", NULL);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%s NULL");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%s NULL");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_cb(TestBatch *batch) {
+test_vcatf_cb(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar ZEKE baz");
     CharBuf *catworthy = S_get_cb("ZEKE");
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %o baz", catworthy);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o CharBuf");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%o CharBuf");
     DECREF(catworthy);
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_obj(TestBatch *batch) {
+test_vcatf_obj(TestBatchRunner *runner) {
     CharBuf   *wanted = S_get_cb("ooga 20 booga");
     Integer32 *i32 = Int32_new(20);
     CharBuf   *got = S_get_cb("ooga");
     CB_catf(got, " %o booga", i32);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o Obj");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%o Obj");
     DECREF(i32);
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_null_obj(TestBatch *batch) {
+test_vcatf_null_obj(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar [NULL] baz");
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %o baz", NULL);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%o NULL");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%o NULL");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_i8(TestBatch *batch) {
+test_vcatf_i8(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar -3 baz");
     int8_t num = -3;
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %i8 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%i8");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%i8");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_i32(TestBatch *batch) {
+test_vcatf_i32(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar -100000 baz");
     int32_t num = -100000;
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %i32 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%i32");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%i32");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_i64(TestBatch *batch) {
+test_vcatf_i64(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar -5000000000 baz");
     int64_t num = INT64_C(-5000000000);
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %i64 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%i64");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%i64");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_u8(TestBatch *batch) {
+test_vcatf_u8(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar 3 baz");
     uint8_t num = 3;
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %u8 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u8");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%u8");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_u32(TestBatch *batch) {
+test_vcatf_u32(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar 100000 baz");
     uint32_t num = 100000;
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %u32 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u32");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%u32");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_u64(TestBatch *batch) {
+test_vcatf_u64(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo bar 5000000000 baz");
     uint64_t num = UINT64_C(5000000000);
     CharBuf *got = S_get_cb("foo ");
     CB_catf(got, "bar %u64 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%u64");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%u64");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_f64(TestBatch *batch) {
+test_vcatf_f64(TestBatchRunner *runner) {
     CharBuf *wanted;
     char buf[64];
     float num = 1.3f;
@@ -377,13 +371,13 @@ test_vcatf_f64(TestBatch *batch) {
     sprintf(buf, "foo bar %g baz", num);
     wanted = CB_new_from_trusted_utf8(buf, strlen(buf));
     CB_catf(got, "bar %f64 baz", num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%f64");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%f64");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_vcatf_x32(TestBatch *batch) {
+test_vcatf_x32(TestBatchRunner *runner) {
     CharBuf *wanted;
     char buf[64];
     unsigned long num = INT32_MAX;
@@ -395,48 +389,48 @@ test_vcatf_x32(TestBatch *batch) {
 #endif
     wanted = CB_new_from_trusted_utf8(buf, strlen(buf));
     CB_catf(got, "bar %x32 baz", (uint32_t)num);
-    TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "%%x32");
+    TEST_TRUE(runner, CB_Equals(wanted, (Obj*)got), "%%x32");
     DECREF(wanted);
     DECREF(got);
 }
 
 static void
-test_serialization(TestBatch *batch) {
+test_serialization(TestBatchRunner *runner) {
     CharBuf *wanted = S_get_cb("foo");
     CharBuf *got    = (CharBuf*)TestUtils_freeze_thaw((Obj*)wanted);
-    TEST_TRUE(batch, got && CB_Equals(wanted, (Obj*)got),
+    TEST_TRUE(runner, got && CB_Equals(wanted, (Obj*)got),
               "Round trip through FREEZE/THAW");
     DECREF(got);
     DECREF(wanted);
 }
 
 void
-TestCB_run_tests(TestCharBuf *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_vcatf_s(batch);
-    test_vcatf_null_string(batch);
-    test_vcatf_cb(batch);
-    test_vcatf_obj(batch);
-    test_vcatf_null_obj(batch);
-    test_vcatf_i8(batch);
-    test_vcatf_i32(batch);
-    test_vcatf_i64(batch);
-    test_vcatf_u8(batch);
-    test_vcatf_u32(batch);
-    test_vcatf_u64(batch);
-    test_vcatf_f64(batch);
-    test_vcatf_x32(batch);
-    test_Cat(batch);
-    test_Mimic_and_Clone(batch);
-    test_Code_Point_At_and_From(batch);
-    test_Find(batch);
-    test_SubString(batch);
-    test_Nip_and_Chop(batch);
-    test_Truncate(batch);
-    test_Trim(batch);
-    test_To_F64(batch);
-    test_To_I64(batch);
-    test_serialization(batch);
+TestCB_run(TestCharBuf *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 55);
+    test_vcatf_s(runner);
+    test_vcatf_null_string(runner);
+    test_vcatf_cb(runner);
+    test_vcatf_obj(runner);
+    test_vcatf_null_obj(runner);
+    test_vcatf_i8(runner);
+    test_vcatf_i32(runner);
+    test_vcatf_i64(runner);
+    test_vcatf_u8(runner);
+    test_vcatf_u32(runner);
+    test_vcatf_u64(runner);
+    test_vcatf_f64(runner);
+    test_vcatf_x32(runner);
+    test_Cat(runner);
+    test_Mimic_and_Clone(runner);
+    test_Code_Point_At_and_From(runner);
+    test_Find(runner);
+    test_SubString(runner);
+    test_Nip_and_Chop(runner);
+    test_Truncate(runner);
+    test_Trim(runner);
+    test_To_F64(runner);
+    test_To_I64(runner);
+    test_serialization(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestCharBuf.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestCharBuf.cfh b/core/Clownfish/Test/TestCharBuf.cfh
index ba27bdb..3cc5d43 100644
--- a/core/Clownfish/Test/TestCharBuf.cfh
+++ b/core/Clownfish/Test/TestCharBuf.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::TestCharBuf cnick TestCB
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestCharBuf*
-    new(TestFormatter *formatter);
-
-    inert TestCharBuf*
-    init(TestCharBuf *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestCharBuf *self);
+    Run(TestCharBuf *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestErr.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestErr.c b/core/Clownfish/Test/TestErr.c
index 7839de5..ddf0457 100644
--- a/core/Clownfish/Test/TestErr.c
+++ b/core/Clownfish/Test/TestErr.c
@@ -22,35 +22,29 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/VTable.h"
 
 TestErr*
-TestErr_new(TestFormatter *formatter) {
-    TestErr *self = (TestErr*)VTable_Make_Obj(TESTERR);
-    return TestErr_init(self, formatter);
-}
-
-TestErr*
-TestErr_init(TestErr *self, TestFormatter *formatter) {
-    return (TestErr*)TestBatch_init((TestBatch*)self, 1, formatter);
+TestErr_new() {
+    return (TestErr*)VTable_Make_Obj(TESTERR);
 }
 
 static void
-test_To_String(TestBatch *batch) {
+test_To_String(TestBatchRunner *runner) {
     CharBuf *message = CB_newf("oops");
     Err *error = Err_new(message);
     CharBuf *string = Err_To_String(error);
-    TEST_TRUE(batch, CB_Equals(message, (Obj*)string),
+    TEST_TRUE(runner, CB_Equals(message, (Obj*)string),
               "Stringifies as message");
     DECREF(string);
     DECREF(error);
 }
 
 void
-TestErr_run_tests(TestErr *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_To_String(batch);
+TestErr_run(TestErr *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 1);
+    test_To_String(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestErr.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestErr.cfh b/core/Clownfish/Test/TestErr.cfh
index 4efd467..178017c 100644
--- a/core/Clownfish/Test/TestErr.cfh
+++ b/core/Clownfish/Test/TestErr.cfh
@@ -20,12 +20,9 @@ class Clownfish::Test::TestErr
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestErr*
-    new(TestFormatter *formatter);
-
-    inert TestErr*
-    init(TestErr *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestErr *self);
+    Run(TestErr *self, TestBatchRunner *runner);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestHash.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestHash.c b/core/Clownfish/Test/TestHash.c
index 6b72ec7..c5e899a 100644
--- a/core/Clownfish/Test/TestHash.c
+++ b/core/Clownfish/Test/TestHash.c
@@ -26,41 +26,35 @@
 #include "Clownfish/Hash.h"
 #include "Clownfish/Num.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VArray.h"
 #include "Clownfish/VTable.h"
 
 TestHash*
-TestHash_new(TestFormatter *formatter) {
-    TestHash *self = (TestHash*)VTable_Make_Obj(TESTHASH);
-    return TestHash_init(self, formatter);
-}
-
-TestHash*
-TestHash_init(TestHash *self, TestFormatter *formatter) {
-    return (TestHash*)TestBatch_init((TestBatch*)self, 29, formatter);
+TestHash_new() {
+    return (TestHash*)VTable_Make_Obj(TESTHASH);
 }
 
 static void
-test_Equals(TestBatch *batch) {
+test_Equals(TestBatchRunner *runner) {
     Hash *hash  = Hash_new(0);
     Hash *other = Hash_new(0);
     ZombieCharBuf *stuff = ZCB_WRAP_STR("stuff", 5);
 
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)other),
+    TEST_TRUE(runner, Hash_Equals(hash, (Obj*)other),
               "Empty hashes are equal");
 
     Hash_Store_Str(hash, "foo", 3, (Obj*)CFISH_TRUE);
-    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)other),
+    TEST_FALSE(runner, Hash_Equals(hash, (Obj*)other),
                "Add one pair and Equals returns false");
 
     Hash_Store_Str(other, "foo", 3, (Obj*)CFISH_TRUE);
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)other),
+    TEST_TRUE(runner, Hash_Equals(hash, (Obj*)other),
               "Add a matching pair and Equals returns true");
 
     Hash_Store_Str(other, "foo", 3, INCREF(stuff));
-    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)other),
+    TEST_FALSE(runner, Hash_Equals(hash, (Obj*)other),
                "Non-matching value spoils Equals");
 
     DECREF(hash);
@@ -68,7 +62,7 @@ test_Equals(TestBatch *batch) {
 }
 
 static void
-test_Store_and_Fetch(TestBatch *batch) {
+test_Store_and_Fetch(TestBatchRunner *runner) {
     Hash          *hash         = Hash_new(100);
     Hash          *dupe         = Hash_new(100);
     const uint32_t starting_cap = Hash_Get_Capacity(hash);
@@ -84,9 +78,9 @@ test_Store_and_Fetch(TestBatch *batch) {
         Hash_Store(dupe, (Obj*)cb, INCREF(cb));
         VA_Push(expected, INCREF(cb));
     }
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)dupe), "Equals");
+    TEST_TRUE(runner, Hash_Equals(hash, (Obj*)dupe), "Equals");
 
-    TEST_INT_EQ(batch, Hash_Get_Capacity(hash), starting_cap,
+    TEST_INT_EQ(runner, Hash_Get_Capacity(hash), starting_cap,
                 "Initial capacity sufficient (no rebuilds)");
 
     for (int32_t i = 0; i < 100; i++) {
@@ -95,37 +89,37 @@ test_Store_and_Fetch(TestBatch *batch) {
         VA_Push(got, (Obj*)INCREF(elem));
     }
 
-    TEST_TRUE(batch, VA_Equals(got, (Obj*)expected),
+    TEST_TRUE(runner, VA_Equals(got, (Obj*)expected),
               "basic Store and Fetch");
-    TEST_INT_EQ(batch, Hash_Get_Size(hash), 100,
+    TEST_INT_EQ(runner, Hash_Get_Size(hash), 100,
                 "size incremented properly by Hash_Store");
 
-    TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)foo) == NULL,
+    TEST_TRUE(runner, Hash_Fetch(hash, (Obj*)foo) == NULL,
               "Fetch against non-existent key returns NULL");
 
     Hash_Store(hash, (Obj*)forty, INCREF(foo));
-    TEST_TRUE(batch, ZCB_Equals(foo, Hash_Fetch(hash, (Obj*)forty)),
+    TEST_TRUE(runner, ZCB_Equals(foo, Hash_Fetch(hash, (Obj*)forty)),
               "Hash_Store replaces existing value");
-    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)dupe),
+    TEST_FALSE(runner, Hash_Equals(hash, (Obj*)dupe),
                "replacement value spoils equals");
-    TEST_INT_EQ(batch, Hash_Get_Size(hash), 100,
+    TEST_INT_EQ(runner, Hash_Get_Size(hash), 100,
                 "size unaffected after value replaced");
 
-    TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == (Obj*)foo,
+    TEST_TRUE(runner, Hash_Delete(hash, (Obj*)forty) == (Obj*)foo,
               "Delete returns value");
     DECREF(foo);
-    TEST_INT_EQ(batch, Hash_Get_Size(hash), 99,
+    TEST_INT_EQ(runner, Hash_Get_Size(hash), 99,
                 "size decremented by successful Delete");
-    TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == NULL,
+    TEST_TRUE(runner, Hash_Delete(hash, (Obj*)forty) == NULL,
               "Delete returns NULL when key not found");
-    TEST_INT_EQ(batch, Hash_Get_Size(hash), 99,
+    TEST_INT_EQ(runner, Hash_Get_Size(hash), 99,
                 "size not decremented by unsuccessful Delete");
     DECREF(Hash_Delete(dupe, (Obj*)forty));
-    TEST_TRUE(batch, VA_Equals(got, (Obj*)expected), "Equals after Delete");
+    TEST_TRUE(runner, VA_Equals(got, (Obj*)expected), "Equals after Delete");
 
     Hash_Clear(hash);
-    TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)twenty) == NULL, "Clear");
-    TEST_TRUE(batch, Hash_Get_Size(hash) == 0, "size is 0 after Clear");
+    TEST_TRUE(runner, Hash_Fetch(hash, (Obj*)twenty) == NULL, "Clear");
+    TEST_TRUE(runner, Hash_Get_Size(hash) == 0, "size is 0 after Clear");
 
     DECREF(hash);
     DECREF(dupe);
@@ -134,7 +128,7 @@ test_Store_and_Fetch(TestBatch *batch) {
 }
 
 static void
-test_Keys_Values_Iter(TestBatch *batch) {
+test_Keys_Values_Iter(TestBatchRunner *runner) {
     Hash     *hash     = Hash_new(0); // trigger multiple rebuilds.
     VArray   *expected = VA_new(100);
     VArray   *keys;
@@ -152,8 +146,8 @@ test_Keys_Values_Iter(TestBatch *batch) {
     values = Hash_Values(hash);
     VA_Sort(keys, NULL, NULL);
     VA_Sort(values, NULL, NULL);
-    TEST_TRUE(batch, VA_Equals(keys, (Obj*)expected), "Keys");
-    TEST_TRUE(batch, VA_Equals(values, (Obj*)expected), "Values");
+    TEST_TRUE(runner, VA_Equals(keys, (Obj*)expected), "Keys");
+    TEST_TRUE(runner, VA_Equals(values, (Obj*)expected), "Values");
     VA_Clear(keys);
     VA_Clear(values);
 
@@ -169,16 +163,16 @@ test_Keys_Values_Iter(TestBatch *batch) {
 
     VA_Sort(keys, NULL, NULL);
     VA_Sort(values, NULL, NULL);
-    TEST_TRUE(batch, VA_Equals(keys, (Obj*)expected), "Keys from Iter");
-    TEST_TRUE(batch, VA_Equals(values, (Obj*)expected), "Values from Iter");
+    TEST_TRUE(runner, VA_Equals(keys, (Obj*)expected), "Keys from Iter");
+    TEST_TRUE(runner, VA_Equals(values, (Obj*)expected), "Values from Iter");
 
     {
         ZombieCharBuf *forty = ZCB_WRAP_STR("40", 2);
         ZombieCharBuf *nope  = ZCB_WRAP_STR("nope", 4);
         Obj *key = Hash_Find_Key(hash, (Obj*)forty, ZCB_Hash_Sum(forty));
-        TEST_TRUE(batch, Obj_Equals(key, (Obj*)forty), "Find_Key");
+        TEST_TRUE(runner, Obj_Equals(key, (Obj*)forty), "Find_Key");
         key = Hash_Find_Key(hash, (Obj*)nope, ZCB_Hash_Sum(nope)),
-        TEST_TRUE(batch, key == NULL,
+        TEST_TRUE(runner, key == NULL,
                   "Find_Key returns NULL for non-existent key");
     }
 
@@ -189,7 +183,7 @@ test_Keys_Values_Iter(TestBatch *batch) {
 }
 
 static void
-test_Dump_and_Load(TestBatch *batch) {
+test_Dump_and_Load(TestBatchRunner *runner) {
     Hash *hash = Hash_new(0);
     Obj  *dump;
     Hash *loaded;
@@ -198,7 +192,7 @@ test_Dump_and_Load(TestBatch *batch) {
                    (Obj*)CB_new_from_trusted_utf8("foo", 3));
     dump = (Obj*)Hash_Dump(hash);
     loaded = (Hash*)Obj_Load(dump, dump);
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)loaded),
+    TEST_TRUE(runner, Hash_Equals(hash, (Obj*)loaded),
               "Dump => Load round trip");
     DECREF(dump);
     DECREF(loaded);
@@ -210,7 +204,7 @@ test_Dump_and_Load(TestBatch *batch) {
     dump = (Obj*)Hash_Dump(hash);
     loaded = (Hash*)Obj_Load(dump, dump);
 
-    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)loaded),
+    TEST_TRUE(runner, Hash_Equals(hash, (Obj*)loaded),
               "Load still works with _class if it's not a real class");
     DECREF(dump);
     DECREF(loaded);
@@ -221,7 +215,7 @@ test_Dump_and_Load(TestBatch *batch) {
 }
 
 static void
-test_serialization(TestBatch *batch) {
+test_serialization(TestBatchRunner *runner) {
     Hash  *wanted = Hash_new(0);
     Hash  *got;
 
@@ -233,7 +227,7 @@ test_serialization(TestBatch *batch) {
     }
 
     got = (Hash*)TestUtils_freeze_thaw((Obj*)wanted);
-    TEST_TRUE(batch, got && Hash_Equals(wanted, (Obj*)got),
+    TEST_TRUE(runner, got && Hash_Equals(wanted, (Obj*)got),
               "Round trip through serialization.");
 
     DECREF(got);
@@ -241,7 +235,7 @@ test_serialization(TestBatch *batch) {
 }
 
 static void
-test_stress(TestBatch *batch) {
+test_stress(TestBatchRunner *runner) {
     Hash     *hash     = Hash_new(0); // trigger multiple rebuilds.
     VArray   *expected = VA_new(1000);
     VArray   *keys;
@@ -269,8 +263,8 @@ test_stress(TestBatch *batch) {
     values = Hash_Values(hash);
     VA_Sort(keys, NULL, NULL);
     VA_Sort(values, NULL, NULL);
-    TEST_TRUE(batch, VA_Equals(keys, (Obj*)expected), "stress Keys");
-    TEST_TRUE(batch, VA_Equals(values, (Obj*)expected), "stress Values");
+    TEST_TRUE(runner, VA_Equals(keys, (Obj*)expected), "stress Keys");
+    TEST_TRUE(runner, VA_Equals(values, (Obj*)expected), "stress Values");
 
     DECREF(keys);
     DECREF(values);
@@ -279,15 +273,15 @@ test_stress(TestBatch *batch) {
 }
 
 void
-TestHash_run_tests(TestHash *self) {
-    TestBatch *batch = (TestBatch*)self;
+TestHash_run(TestHash *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 29);
     srand((unsigned int)time((time_t*)NULL));
-    test_Equals(batch);
-    test_Store_and_Fetch(batch);
-    test_Keys_Values_Iter(batch);
-    test_Dump_and_Load(batch);
-    test_serialization(batch);
-    test_stress(batch);
+    test_Equals(runner);
+    test_Store_and_Fetch(runner);
+    test_Keys_Values_Iter(runner);
+    test_Dump_and_Load(runner);
+    test_serialization(runner);
+    test_stress(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestHash.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestHash.cfh b/core/Clownfish/Test/TestHash.cfh
index cc74687..a730105 100644
--- a/core/Clownfish/Test/TestHash.cfh
+++ b/core/Clownfish/Test/TestHash.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::TestHash
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestHash*
-    new(TestFormatter *formatter);
-
-    inert TestHash*
-    init(TestHash *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestHash *self);
+    Run(TestHash *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestLockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestLockFreeRegistry.c b/core/Clownfish/Test/TestLockFreeRegistry.c
index dcd5e8b..d895595 100644
--- a/core/Clownfish/Test/TestLockFreeRegistry.c
+++ b/core/Clownfish/Test/TestLockFreeRegistry.c
@@ -24,18 +24,12 @@
 
 #include "Clownfish/LockFreeRegistry.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/VTable.h"
 
 TestLockFreeRegistry*
-TestLFReg_new(TestFormatter *formatter) {
-    TestLockFreeRegistry *self = (TestLockFreeRegistry*)VTable_Make_Obj(TESTLOCKFREEREGISTRY);
-    return TestLFReg_init(self, formatter);
-}
-
-TestLockFreeRegistry*
-TestLFReg_init(TestLockFreeRegistry *self, TestFormatter *formatter) {
-    return (TestLockFreeRegistry*)TestBatch_init((TestBatch*)self, 6, formatter);
+TestLFReg_new() {
+    return (TestLockFreeRegistry*)VTable_Make_Obj(TESTLOCKFREEREGISTRY);
 }
 
 StupidHashCharBuf*
@@ -50,27 +44,27 @@ StupidHashCharBuf_hash_sum(StupidHashCharBuf *self) {
 }
 
 static void
-test_all(TestBatch *batch) {
+test_all(TestBatchRunner *runner) {
     LockFreeRegistry *registry = LFReg_new(10);
     StupidHashCharBuf *foo = StupidHashCharBuf_new("foo");
     StupidHashCharBuf *bar = StupidHashCharBuf_new("bar");
     StupidHashCharBuf *baz = StupidHashCharBuf_new("baz");
     StupidHashCharBuf *foo_dupe = StupidHashCharBuf_new("foo");
 
-    TEST_TRUE(batch, LFReg_Register(registry, (Obj*)foo, (Obj*)foo),
+    TEST_TRUE(runner, LFReg_Register(registry, (Obj*)foo, (Obj*)foo),
               "Register() returns true on success");
-    TEST_FALSE(batch,
+    TEST_FALSE(runner,
                LFReg_Register(registry, (Obj*)foo_dupe, (Obj*)foo_dupe),
                "Can't Register() keys that test equal");
 
-    TEST_TRUE(batch, LFReg_Register(registry, (Obj*)bar, (Obj*)bar),
+    TEST_TRUE(runner, LFReg_Register(registry, (Obj*)bar, (Obj*)bar),
               "Register() key with the same Hash_Sum but that isn't Equal");
 
-    TEST_TRUE(batch, LFReg_Fetch(registry, (Obj*)foo_dupe) == (Obj*)foo,
+    TEST_TRUE(runner, LFReg_Fetch(registry, (Obj*)foo_dupe) == (Obj*)foo,
               "Fetch()");
-    TEST_TRUE(batch, LFReg_Fetch(registry, (Obj*)bar) == (Obj*)bar,
+    TEST_TRUE(runner, LFReg_Fetch(registry, (Obj*)bar) == (Obj*)bar,
               "Fetch() again");
-    TEST_TRUE(batch, LFReg_Fetch(registry, (Obj*)baz) == NULL,
+    TEST_TRUE(runner, LFReg_Fetch(registry, (Obj*)baz) == NULL,
               "Fetch() non-existent key returns NULL");
 
     DECREF(foo_dupe);
@@ -81,9 +75,9 @@ test_all(TestBatch *batch) {
 }
 
 void
-TestLFReg_run_tests(TestLockFreeRegistry *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_all(batch);
+TestLFReg_run(TestLockFreeRegistry *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
+    test_all(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestLockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestLockFreeRegistry.cfh b/core/Clownfish/Test/TestLockFreeRegistry.cfh
index 376fbe2..a3a3675 100644
--- a/core/Clownfish/Test/TestLockFreeRegistry.cfh
+++ b/core/Clownfish/Test/TestLockFreeRegistry.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::TestLockFreeRegistry cnick TestLFReg
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestLockFreeRegistry*
-    new(TestFormatter *formatter);
-
-    inert TestLockFreeRegistry*
-    init(TestLockFreeRegistry *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestLockFreeRegistry *self);
+    Run(TestLockFreeRegistry *self, TestBatchRunner *runner);
 }
 
 /** Private test-only class for stressing LockFreeRegistry.

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestNum.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestNum.c b/core/Clownfish/Test/TestNum.c
index add9a65..2b05659 100644
--- a/core/Clownfish/Test/TestNum.c
+++ b/core/Clownfish/Test/TestNum.c
@@ -22,23 +22,17 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Num.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/TestHarness/TestUtils.h"
 #include "Clownfish/VTable.h"
 
 TestNum*
-TestNum_new(TestFormatter *formatter) {
-    TestNum *self = (TestNum*)VTable_Make_Obj(TESTNUM);
-    return TestNum_init(self, formatter);
-}
-
-TestNum*
-TestNum_init(TestNum *self, TestFormatter *formatter) {
-    return (TestNum*)TestBatch_init((TestBatch*)self, 58, formatter);
+TestNum_new() {
+    return (TestNum*)VTable_Make_Obj(TESTNUM);
 }
 
 static void
-test_To_String(TestBatch *batch) {
+test_To_String(TestBatchRunner *runner) {
     Float32   *f32 = Float32_new(1.33f);
     Float64   *f64 = Float64_new(1.33);
     Integer32 *i32 = Int32_new(INT32_MAX);
@@ -50,17 +44,17 @@ test_To_String(TestBatch *batch) {
     CharBuf *true_string  = Bool_To_String(CFISH_TRUE);
     CharBuf *false_string = Bool_To_String(CFISH_FALSE);
 
-    TEST_TRUE(batch, CB_Starts_With_Str(f32_string, "1.3", 3),
+    TEST_TRUE(runner, CB_Starts_With_Str(f32_string, "1.3", 3),
               "Float32_To_String");
-    TEST_TRUE(batch, CB_Starts_With_Str(f64_string, "1.3", 3),
+    TEST_TRUE(runner, CB_Starts_With_Str(f64_string, "1.3", 3),
               "Float64_To_String");
-    TEST_TRUE(batch, CB_Equals_Str(i32_string, "2147483647", 10),
+    TEST_TRUE(runner, CB_Equals_Str(i32_string, "2147483647", 10),
               "Int32_To_String");
-    TEST_TRUE(batch, CB_Equals_Str(i64_string, "9223372036854775807", 19),
+    TEST_TRUE(runner, CB_Equals_Str(i64_string, "9223372036854775807", 19),
               "Int64_To_String");
-    TEST_TRUE(batch, CB_Equals_Str(true_string, "true", 4),
+    TEST_TRUE(runner, CB_Equals_Str(true_string, "true", 4),
               "Bool_To_String [true]");
-    TEST_TRUE(batch, CB_Equals_Str(false_string, "false", 5),
+    TEST_TRUE(runner, CB_Equals_Str(false_string, "false", 5),
               "Bool_To_String [false]");
 
     DECREF(false_string);
@@ -76,7 +70,7 @@ test_To_String(TestBatch *batch) {
 }
 
 static void
-test_accessors(TestBatch *batch) {
+test_accessors(TestBatchRunner *runner) {
     Float32   *f32 = Float32_new(1.0);
     Float64   *f64 = Float64_new(1.0);
     Integer32 *i32 = Int32_new(1);
@@ -87,49 +81,49 @@ test_accessors(TestBatch *batch) {
     double got64;
 
     Float32_Set_Value(f32, 1.33f);
-    TEST_FLOAT_EQ(batch, Float32_Get_Value(f32), 1.33f,
+    TEST_FLOAT_EQ(runner, Float32_Get_Value(f32), 1.33f,
                   "F32 Set_Value Get_Value");
 
     Float64_Set_Value(f64, 1.33);
     got64 = Float64_Get_Value(f64);
-    TEST_TRUE(batch, *(int64_t*)&got64 == *(int64_t*)&wanted64,
+    TEST_TRUE(runner, *(int64_t*)&got64 == *(int64_t*)&wanted64,
               "F64 Set_Value Get_Value");
 
-    TEST_TRUE(batch, Float32_To_I64(f32) == 1, "Float32_To_I64");
-    TEST_TRUE(batch, Float64_To_I64(f64) == 1, "Float64_To_I64");
+    TEST_TRUE(runner, Float32_To_I64(f32) == 1, "Float32_To_I64");
+    TEST_TRUE(runner, Float64_To_I64(f64) == 1, "Float64_To_I64");
 
     got32 = (float)Float32_To_F64(f32);
-    TEST_TRUE(batch, *(int32_t*)&got32 == *(int32_t*)&wanted32,
+    TEST_TRUE(runner, *(int32_t*)&got32 == *(int32_t*)&wanted32,
               "Float32_To_F64");
 
     got64 = Float64_To_F64(f64);
-    TEST_TRUE(batch, *(int64_t*)&got64 == *(int64_t*)&wanted64,
+    TEST_TRUE(runner, *(int64_t*)&got64 == *(int64_t*)&wanted64,
               "Float64_To_F64");
 
     Int32_Set_Value(i32, INT32_MIN);
-    TEST_INT_EQ(batch, Int32_Get_Value(i32), INT32_MIN,
+    TEST_INT_EQ(runner, Int32_Get_Value(i32), INT32_MIN,
                 "I32 Set_Value Get_Value");
 
     Int64_Set_Value(i64, INT64_MIN);
-    TEST_TRUE(batch, Int64_Get_Value(i64) == INT64_MIN,
+    TEST_TRUE(runner, Int64_Get_Value(i64) == INT64_MIN,
               "I64 Set_Value Get_Value");
 
     Int32_Set_Value(i32, -1);
     Int64_Set_Value(i64, -1);
-    TEST_TRUE(batch, Int32_To_F64(i32) == -1, "Int32_To_F64");
-    TEST_TRUE(batch, Int64_To_F64(i64) == -1, "Int64_To_F64");
+    TEST_TRUE(runner, Int32_To_F64(i32) == -1, "Int32_To_F64");
+    TEST_TRUE(runner, Int64_To_F64(i64) == -1, "Int64_To_F64");
 
-    TEST_INT_EQ(batch, Bool_Get_Value(CFISH_TRUE), true,
+    TEST_INT_EQ(runner, Bool_Get_Value(CFISH_TRUE), true,
                 "Bool_Get_Value [true]");
-    TEST_INT_EQ(batch, Bool_Get_Value(CFISH_FALSE), false,
+    TEST_INT_EQ(runner, Bool_Get_Value(CFISH_FALSE), false,
                 "Bool_Get_Value [false]");
-    TEST_TRUE(batch, Bool_To_I64(CFISH_TRUE) == true,
+    TEST_TRUE(runner, Bool_To_I64(CFISH_TRUE) == true,
               "Bool_To_I64 [true]");
-    TEST_TRUE(batch, Bool_To_I64(CFISH_FALSE) == false,
+    TEST_TRUE(runner, Bool_To_I64(CFISH_FALSE) == false,
               "Bool_To_I64 [false]");
-    TEST_TRUE(batch, Bool_To_F64(CFISH_TRUE) == 1.0,
+    TEST_TRUE(runner, Bool_To_F64(CFISH_TRUE) == 1.0,
               "Bool_To_F64 [true]");
-    TEST_TRUE(batch, Bool_To_F64(CFISH_FALSE) == 0.0,
+    TEST_TRUE(runner, Bool_To_F64(CFISH_FALSE) == 0.0,
               "Bool_To_F64 [false]");
 
     DECREF(i64);
@@ -139,74 +133,74 @@ test_accessors(TestBatch *batch) {
 }
 
 static void
-test_Equals_and_Compare_To(TestBatch *batch) {
+test_Equals_and_Compare_To(TestBatchRunner *runner) {
     Float32   *f32 = Float32_new(1.0);
     Float64   *f64 = Float64_new(1.0);
     Integer32 *i32 = Int32_new(INT32_MAX);
     Integer64 *i64 = Int64_new(INT64_MAX);
 
-    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)f64) == 0,
+    TEST_TRUE(runner, Float32_Compare_To(f32, (Obj*)f64) == 0,
               "F32_Compare_To equal");
-    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f64),
+    TEST_TRUE(runner, Float32_Equals(f32, (Obj*)f64),
               "F32_Equals equal");
 
     Float64_Set_Value(f64, 2.0);
-    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)f64) < 0,
+    TEST_TRUE(runner, Float32_Compare_To(f32, (Obj*)f64) < 0,
               "F32_Compare_To less than");
-    TEST_FALSE(batch, Float32_Equals(f32, (Obj*)f64),
+    TEST_FALSE(runner, Float32_Equals(f32, (Obj*)f64),
                "F32_Equals less than");
 
     Float64_Set_Value(f64, 0.0);
-    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)f64) > 0,
+    TEST_TRUE(runner, Float32_Compare_To(f32, (Obj*)f64) > 0,
               "F32_Compare_To greater than");
-    TEST_FALSE(batch, Float32_Equals(f32, (Obj*)f64),
+    TEST_FALSE(runner, Float32_Equals(f32, (Obj*)f64),
                "F32_Equals greater than");
 
     Float64_Set_Value(f64, 1.0);
     Float32_Set_Value(f32, 1.0);
-    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)f32) == 0,
+    TEST_TRUE(runner, Float64_Compare_To(f64, (Obj*)f32) == 0,
               "F64_Compare_To equal");
-    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f32),
+    TEST_TRUE(runner, Float64_Equals(f64, (Obj*)f32),
               "F64_Equals equal");
 
     Float32_Set_Value(f32, 2.0);
-    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)f32) < 0,
+    TEST_TRUE(runner, Float64_Compare_To(f64, (Obj*)f32) < 0,
               "F64_Compare_To less than");
-    TEST_FALSE(batch, Float64_Equals(f64, (Obj*)f32),
+    TEST_FALSE(runner, Float64_Equals(f64, (Obj*)f32),
                "F64_Equals less than");
 
     Float32_Set_Value(f32, 0.0);
-    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)f32) > 0,
+    TEST_TRUE(runner, Float64_Compare_To(f64, (Obj*)f32) > 0,
               "F64_Compare_To greater than");
-    TEST_FALSE(batch, Float64_Equals(f64, (Obj*)f32),
+    TEST_FALSE(runner, Float64_Equals(f64, (Obj*)f32),
                "F64_Equals greater than");
 
     Float64_Set_Value(f64, INT64_MAX * 2.0);
-    TEST_TRUE(batch, Float64_Compare_To(f64, (Obj*)i64) > 0,
+    TEST_TRUE(runner, Float64_Compare_To(f64, (Obj*)i64) > 0,
               "Float64 comparison to Integer64");
-    TEST_TRUE(batch, Int64_Compare_To(i64, (Obj*)f64) < 0,
+    TEST_TRUE(runner, Int64_Compare_To(i64, (Obj*)f64) < 0,
               "Integer64 comparison to Float64");
 
     Float32_Set_Value(f32, INT32_MAX * 2.0f);
-    TEST_TRUE(batch, Float32_Compare_To(f32, (Obj*)i32) > 0,
+    TEST_TRUE(runner, Float32_Compare_To(f32, (Obj*)i32) > 0,
               "Float32 comparison to Integer32");
-    TEST_TRUE(batch, Int32_Compare_To(i32, (Obj*)f32) < 0,
+    TEST_TRUE(runner, Int32_Compare_To(i32, (Obj*)f32) < 0,
               "Integer32 comparison to Float32");
 
     Int64_Set_Value(i64, INT64_C(0x6666666666666666));
     Integer64 *i64_copy = Int64_new(INT64_C(0x6666666666666666));
-    TEST_TRUE(batch, Int64_Compare_To(i64, (Obj*)i64_copy) == 0,
+    TEST_TRUE(runner, Int64_Compare_To(i64, (Obj*)i64_copy) == 0,
               "Integer64 comparison to same number");
 
-    TEST_TRUE(batch, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_TRUE),
+    TEST_TRUE(runner, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_TRUE),
               "CFISH_TRUE Equals itself");
-    TEST_TRUE(batch, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_FALSE),
+    TEST_TRUE(runner, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_FALSE),
               "CFISH_FALSE Equals itself");
-    TEST_FALSE(batch, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_TRUE),
+    TEST_FALSE(runner, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_TRUE),
                "CFISH_FALSE not Equals CFISH_TRUE ");
-    TEST_FALSE(batch, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_FALSE),
+    TEST_FALSE(runner, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_FALSE),
                "CFISH_TRUE not Equals CFISH_FALSE ");
-    TEST_FALSE(batch, Bool_Equals(CFISH_TRUE, (Obj*)CHARBUF),
+    TEST_FALSE(runner, Bool_Equals(CFISH_TRUE, (Obj*)CHARBUF),
                "CFISH_TRUE not Equals random other object ");
 
     DECREF(i64_copy);
@@ -217,7 +211,7 @@ test_Equals_and_Compare_To(TestBatch *batch) {
 }
 
 static void
-test_Clone(TestBatch *batch) {
+test_Clone(TestBatchRunner *runner) {
     Float32   *f32 = Float32_new(1.33f);
     Float64   *f64 = Float64_new(1.33);
     Integer32 *i32 = Int32_new(INT32_MAX);
@@ -226,15 +220,15 @@ test_Clone(TestBatch *batch) {
     Float64   *f64_dupe = Float64_Clone(f64);
     Integer32 *i32_dupe = Int32_Clone(i32);
     Integer64 *i64_dupe = Int64_Clone(i64);
-    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f32_dupe),
+    TEST_TRUE(runner, Float32_Equals(f32, (Obj*)f32_dupe),
               "Float32 Clone");
-    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f64_dupe),
+    TEST_TRUE(runner, Float64_Equals(f64, (Obj*)f64_dupe),
               "Float64 Clone");
-    TEST_TRUE(batch, Int32_Equals(i32, (Obj*)i32_dupe),
+    TEST_TRUE(runner, Int32_Equals(i32, (Obj*)i32_dupe),
               "Integer32 Clone");
-    TEST_TRUE(batch, Int64_Equals(i64, (Obj*)i64_dupe),
+    TEST_TRUE(runner, Int64_Equals(i64, (Obj*)i64_dupe),
               "Integer64 Clone");
-    TEST_TRUE(batch, Bool_Equals(CFISH_TRUE, (Obj*)Bool_Clone(CFISH_TRUE)),
+    TEST_TRUE(runner, Bool_Equals(CFISH_TRUE, (Obj*)Bool_Clone(CFISH_TRUE)),
               "BoolNum Clone");
     DECREF(i64_dupe);
     DECREF(i32_dupe);
@@ -247,7 +241,7 @@ test_Clone(TestBatch *batch) {
 }
 
 static void
-test_Mimic(TestBatch *batch) {
+test_Mimic(TestBatchRunner *runner) {
     Float32   *f32 = Float32_new(1.33f);
     Float64   *f64 = Float64_new(1.33);
     Integer32 *i32 = Int32_new(INT32_MAX);
@@ -260,13 +254,13 @@ test_Mimic(TestBatch *batch) {
     Float64_Mimic(f64_dupe, (Obj*)f64);
     Int32_Mimic(i32_dupe, (Obj*)i32);
     Int64_Mimic(i64_dupe, (Obj*)i64);
-    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f32_dupe),
+    TEST_TRUE(runner, Float32_Equals(f32, (Obj*)f32_dupe),
               "Float32 Mimic");
-    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f64_dupe),
+    TEST_TRUE(runner, Float64_Equals(f64, (Obj*)f64_dupe),
               "Float64 Mimic");
-    TEST_TRUE(batch, Int32_Equals(i32, (Obj*)i32_dupe),
+    TEST_TRUE(runner, Int32_Equals(i32, (Obj*)i32_dupe),
               "Integer32 Mimic");
-    TEST_TRUE(batch, Int64_Equals(i64, (Obj*)i64_dupe),
+    TEST_TRUE(runner, Int64_Equals(i64, (Obj*)i64_dupe),
               "Integer64 Mimic");
     DECREF(i64_dupe);
     DECREF(i32_dupe);
@@ -279,7 +273,7 @@ test_Mimic(TestBatch *batch) {
 }
 
 static void
-test_serialization(TestBatch *batch) {
+test_serialization(TestBatchRunner *runner) {
     Float32   *f32 = Float32_new(1.33f);
     Float64   *f64 = Float64_new(1.33);
     Integer32 *i32 = Int32_new(-1);
@@ -290,15 +284,15 @@ test_serialization(TestBatch *batch) {
     Integer64 *i64_thaw = (Integer64*)TestUtils_freeze_thaw((Obj*)i64);
     BoolNum   *true_thaw = (BoolNum*)TestUtils_freeze_thaw((Obj*)CFISH_TRUE);
 
-    TEST_TRUE(batch, Float32_Equals(f32, (Obj*)f32_thaw),
+    TEST_TRUE(runner, Float32_Equals(f32, (Obj*)f32_thaw),
               "Float32 freeze/thaw");
-    TEST_TRUE(batch, Float64_Equals(f64, (Obj*)f64_thaw),
+    TEST_TRUE(runner, Float64_Equals(f64, (Obj*)f64_thaw),
               "Float64 freeze/thaw");
-    TEST_TRUE(batch, Int32_Equals(i32, (Obj*)i32_thaw),
+    TEST_TRUE(runner, Int32_Equals(i32, (Obj*)i32_thaw),
               "Integer32 freeze/thaw");
-    TEST_TRUE(batch, Int64_Equals(i64, (Obj*)i64_thaw),
+    TEST_TRUE(runner, Int64_Equals(i64, (Obj*)i64_thaw),
               "Integer64 freeze/thaw");
-    TEST_TRUE(batch, Bool_Equals(CFISH_TRUE, (Obj*)true_thaw),
+    TEST_TRUE(runner, Bool_Equals(CFISH_TRUE, (Obj*)true_thaw),
               "BoolNum freeze/thaw");
 
     DECREF(i64_thaw);
@@ -312,14 +306,14 @@ test_serialization(TestBatch *batch) {
 }
 
 void
-TestNum_run_tests(TestNum *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_To_String(batch);
-    test_accessors(batch);
-    test_Equals_and_Compare_To(batch);
-    test_Clone(batch);
-    test_Mimic(batch);
-    test_serialization(batch);
+TestNum_run(TestNum *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 58);
+    test_To_String(runner);
+    test_accessors(runner);
+    test_Equals_and_Compare_To(runner);
+    test_Clone(runner);
+    test_Mimic(runner);
+    test_serialization(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestNum.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestNum.cfh b/core/Clownfish/Test/TestNum.cfh
index 9176210..6d1f663 100644
--- a/core/Clownfish/Test/TestNum.cfh
+++ b/core/Clownfish/Test/TestNum.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::TestNum
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestNum*
-    new(TestFormatter *formatter);
-
-    inert TestNum*
-    init(TestNum *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestNum *self);
+    Run(TestNum *self, TestBatchRunner *runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestObj.c
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestObj.c b/core/Clownfish/Test/TestObj.c
index 63d81f7..f1d6d90 100644
--- a/core/Clownfish/Test/TestObj.c
+++ b/core/Clownfish/Test/TestObj.c
@@ -25,18 +25,12 @@
 #include "Clownfish/CharBuf.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestFormatter.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
 #include "Clownfish/VTable.h"
 
 TestObj*
-TestObj_new(TestFormatter *formatter) {
-    TestObj *self = (TestObj*)VTable_Make_Obj(TESTOBJ);
-    return TestObj_init(self, formatter);
-}
-
-TestObj*
-TestObj_init(TestObj *self, TestFormatter *formatter) {
-    return (TestObj*)TestBatch_init((TestBatch*)self, 20, formatter);
+TestObj_new() {
+    return (TestObj*)VTable_Make_Obj(TESTOBJ);
 }
 
 static Obj*
@@ -52,23 +46,23 @@ S_new_testobj() {
 }
 
 static void
-test_refcounts(TestBatch *batch) {
+test_refcounts(TestBatchRunner *runner) {
     Obj *obj = S_new_testobj();
 
-    TEST_INT_EQ(batch, Obj_Get_RefCount(obj), 1,
+    TEST_INT_EQ(runner, Obj_Get_RefCount(obj), 1,
                 "Correct starting refcount");
 
     Obj_Inc_RefCount(obj);
-    TEST_INT_EQ(batch, Obj_Get_RefCount(obj), 2, "Inc_RefCount");
+    TEST_INT_EQ(runner, Obj_Get_RefCount(obj), 2, "Inc_RefCount");
 
     Obj_Dec_RefCount(obj);
-    TEST_INT_EQ(batch, Obj_Get_RefCount(obj), 1, "Dec_RefCount");
+    TEST_INT_EQ(runner, Obj_Get_RefCount(obj), 1, "Dec_RefCount");
 
     DECREF(obj);
 }
 
 static void
-test_To_String(TestBatch *batch) {
+test_To_String(TestBatchRunner *runner) {
     Obj *testobj = S_new_testobj();
     CharBuf *string = Obj_To_String(testobj);
     ZombieCharBuf *temp = ZCB_WRAP(string);
@@ -76,17 +70,17 @@ test_To_String(TestBatch *batch) {
         if (ZCB_Starts_With_Str(temp, "TestObj", 7)) { break; }
         ZCB_Nip_One(temp);
     }
-    TEST_TRUE(batch, ZCB_Starts_With_Str(temp, "TestObj", 7), "To_String");
+    TEST_TRUE(runner, ZCB_Starts_With_Str(temp, "TestObj", 7), "To_String");
     DECREF(string);
     DECREF(testobj);
 }
 
 static void
-test_Dump(TestBatch *batch) {
+test_Dump(TestBatchRunner *runner) {
     Obj *testobj = S_new_testobj();
     CharBuf *string = Obj_To_String(testobj);
     Obj *dump = Obj_Dump(testobj);
-    TEST_TRUE(batch, Obj_Equals(dump, (Obj*)string),
+    TEST_TRUE(runner, Obj_Equals(dump, (Obj*)string),
               "Default Dump returns To_String");
     DECREF(dump);
     DECREF(string);
@@ -94,13 +88,13 @@ test_Dump(TestBatch *batch) {
 }
 
 static void
-test_Equals(TestBatch *batch) {
+test_Equals(TestBatchRunner *runner) {
     Obj *testobj = S_new_testobj();
     Obj *other   = S_new_testobj();
 
-    TEST_TRUE(batch, Obj_Equals(testobj, testobj),
+    TEST_TRUE(runner, Obj_Equals(testobj, testobj),
               "Equals is true for the same object");
-    TEST_FALSE(batch, Obj_Equals(testobj, other),
+    TEST_FALSE(runner, Obj_Equals(testobj, other),
                "Distinct objects are not equal");
 
     DECREF(testobj);
@@ -108,25 +102,25 @@ test_Equals(TestBatch *batch) {
 }
 
 static void
-test_Hash_Sum(TestBatch *batch) {
+test_Hash_Sum(TestBatchRunner *runner) {
     Obj *testobj = S_new_testobj();
     int64_t address64 = PTR_TO_I64(testobj);
     int32_t address32 = (int32_t)address64;
-    TEST_TRUE(batch, (Obj_Hash_Sum(testobj) == address32),
+    TEST_TRUE(runner, (Obj_Hash_Sum(testobj) == address32),
               "Hash_Sum uses memory address");
     DECREF(testobj);
 }
 
 static void
-test_Is_A(TestBatch *batch) {
+test_Is_A(TestBatchRunner *runner) {
     CharBuf *charbuf   = CB_new(0);
     VTable  *bb_vtable = CB_Get_VTable(charbuf);
     CharBuf *klass     = CB_Get_Class_Name(charbuf);
 
-    TEST_TRUE(batch, CB_Is_A(charbuf, CHARBUF), "CharBuf Is_A CharBuf.");
-    TEST_TRUE(batch, CB_Is_A(charbuf, OBJ), "CharBuf Is_A Obj.");
-    TEST_TRUE(batch, bb_vtable == CHARBUF, "Get_VTable");
-    TEST_TRUE(batch, CB_Equals(VTable_Get_Name(CHARBUF), (Obj*)klass),
+    TEST_TRUE(runner, CB_Is_A(charbuf, CHARBUF), "CharBuf Is_A CharBuf.");
+    TEST_TRUE(runner, CB_Is_A(charbuf, OBJ), "CharBuf Is_A Obj.");
+    TEST_TRUE(runner, bb_vtable == CHARBUF, "Get_VTable");
+    TEST_TRUE(runner, CB_Equals(VTable_Get_Name(CHARBUF), (Obj*)klass),
               "Get_Class_Name");
 
     DECREF(charbuf);
@@ -173,12 +167,12 @@ S_attempt_Mimic(void *context) {
 }
 
 static void
-S_verify_abstract_error(TestBatch *batch, Err_Attempt_t routine,
+S_verify_abstract_error(TestBatchRunner *runner, Err_Attempt_t routine,
                         void *context, const char *name) {
     char message[100];
     sprintf(message, "%s() is abstract", name);
     Err *error = Err_trap(routine, context);
-    TEST_TRUE(batch, error != NULL
+    TEST_TRUE(runner, error != NULL
               && Err_Is_A(error, ERR) 
               && CB_Find_Str(Err_Get_Mess(error), "bstract", 7) != -1,
               message);
@@ -186,31 +180,31 @@ S_verify_abstract_error(TestBatch *batch, Err_Attempt_t routine,
 }
 
 static void
-test_abstract_routines(TestBatch *batch) {
+test_abstract_routines(TestBatchRunner *runner) {
     Obj *blank = VTable_Make_Obj(OBJ);
-    S_verify_abstract_error(batch, S_attempt_init, blank, "init");
+    S_verify_abstract_error(runner, S_attempt_init, blank, "init");
 
     Obj *obj = S_new_testobj();
-    S_verify_abstract_error(batch, S_attempt_Clone,      obj, "Clone");
-    S_verify_abstract_error(batch, S_attempt_Make,       obj, "Make");
-    S_verify_abstract_error(batch, S_attempt_Compare_To, obj, "Compare_To");
-    S_verify_abstract_error(batch, S_attempt_To_I64,     obj, "To_I64");
-    S_verify_abstract_error(batch, S_attempt_To_F64,     obj, "To_F64");
-    S_verify_abstract_error(batch, S_attempt_Load,       obj, "Load");
-    S_verify_abstract_error(batch, S_attempt_Mimic,      obj, "Mimic");
+    S_verify_abstract_error(runner, S_attempt_Clone,      obj, "Clone");
+    S_verify_abstract_error(runner, S_attempt_Make,       obj, "Make");
+    S_verify_abstract_error(runner, S_attempt_Compare_To, obj, "Compare_To");
+    S_verify_abstract_error(runner, S_attempt_To_I64,     obj, "To_I64");
+    S_verify_abstract_error(runner, S_attempt_To_F64,     obj, "To_F64");
+    S_verify_abstract_error(runner, S_attempt_Load,       obj, "Load");
+    S_verify_abstract_error(runner, S_attempt_Mimic,      obj, "Mimic");
     DECREF(obj);
 }
 
 void
-TestObj_run_tests(TestObj *self) {
-    TestBatch *batch = (TestBatch*)self;
-    test_refcounts(batch);
-    test_To_String(batch);
-    test_Dump(batch);
-    test_Equals(batch);
-    test_Hash_Sum(batch);
-    test_Is_A(batch);
-    test_abstract_routines(batch);
+TestObj_run(TestObj *self, TestBatchRunner *runner) {
+    TestBatchRunner_Plan(runner, (TestBatch*)self, 20);
+    test_refcounts(runner);
+    test_To_String(runner);
+    test_Dump(runner);
+    test_Equals(runner);
+    test_Hash_Sum(runner);
+    test_Is_A(runner);
+    test_abstract_routines(runner);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/3da6ebd3/core/Clownfish/Test/TestObj.cfh
----------------------------------------------------------------------
diff --git a/core/Clownfish/Test/TestObj.cfh b/core/Clownfish/Test/TestObj.cfh
index 3cca164..eb4a0b6 100644
--- a/core/Clownfish/Test/TestObj.cfh
+++ b/core/Clownfish/Test/TestObj.cfh
@@ -20,13 +20,10 @@ class Clownfish::Test::TestObj
     inherits Clownfish::TestHarness::TestBatch {
 
     inert incremented TestObj*
-    new(TestFormatter *formatter);
-
-    inert TestObj*
-    init(TestObj *self, TestFormatter *formatter);
+    new();
 
     void
-    Run_Tests(TestObj *self);
+    Run(TestObj *self, TestBatchRunner *runner);
 }