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/28 19:47:49 UTC
[lucy-commits] [16/19] git commit: refs/heads/separate-clownfish-wip1 - Move
Clownfish runtime tests to a separate parcel
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/a51ff172
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/a51ff172
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/a51ff172
Branch: refs/heads/separate-clownfish-wip1
Commit: a51ff172681ed183673c3173f56ad48ff14e082f
Parents: c2eee72
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 27 19:40:10 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Tue May 28 17:07:28 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/a51ff172/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/a51ff172/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/common/charmonizer.c b/common/charmonizer.c
index 21cc5b3..200f570 100644
--- a/common/charmonizer.c
+++ b/common/charmonizer.c
@@ -6803,6 +6803,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);
}
@@ -6959,6 +6960,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);
@@ -7001,6 +7006,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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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/a51ff172/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);
+}
+
+