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 2016/07/11 11:25:34 UTC
[01/14] lucy-clownfish git commit: Add "xs_prereqs" module parameter
Repository: lucy-clownfish
Updated Branches:
refs/heads/master 56f1982e7 -> 0be314b9d
Add "xs_prereqs" module parameter
This parameter lists the names of other Clownfish XS modules whose
symbols are referenced from a module. The corresponding libraries
are linked against on Windows.
This obviates the need to call cf_linker_flags manually.
If we start to install parcel metadata, it should be possible to
determine the XS prerequisites automatically (see CLOWNFISH-83).
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/a80e405e
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/a80e405e
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/a80e405e
Branch: refs/heads/master
Commit: a80e405ea7878f2eafc3562ab35c3e9ba6eff0c4
Parents: 24fb4d9
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 8 13:57:27 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 8 14:25:36 2016 +0200
----------------------------------------------------------------------
compiler/perl/lib/Clownfish/CFC/Perl/Build.pm | 26 +++++++++-------------
1 file changed, 11 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a80e405e/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
index 6d0f584..9c1ff84 100644
--- a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
+++ b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
@@ -134,7 +134,7 @@ sub cf_base_path {
}
sub cf_linker_flags {
- my $self_or_class = shift;
+ my $self = shift;
my $dlext = $Config{dlext};
# Only needed on Windows
@@ -152,7 +152,7 @@ sub cf_linker_flags {
my $lib_file;
my $found;
- for my $dir (@INC) {
+ for my $dir ( catdir( $self->blib, 'arch' ), @INC ) {
$lib_file = catfile(
$dir, 'auto', @module_parts, "$class_name.$ext",
);
@@ -503,13 +503,19 @@ sub _compile_custom_xs {
# .o => .(a|bundle)
my $lib_file = catfile( $archdir, "$class_name.$Config{dlext}" );
if ( !$self->up_to_date( [ @objects, $AUTOGEN_DIR ], $lib_file ) ) {
+ my $linker_flags = $self->extra_linker_flags;
+ if ( $module->{xs_prereqs} ) {
+ push @$linker_flags,
+ $self->cf_linker_flags( @{ $module->{xs_prereqs} } );
+ }
$cbuilder->link(
module_name => $module_name,
objects => \@objects,
lib_file => $lib_file,
- extra_linker_flags => $self->extra_linker_flags,
+ extra_linker_flags => $linker_flags,
);
# Install .lib file on Windows
+ # TODO: Install .dll.a when building with GCC on Windows?
my $implib_file = catfile( $libdir, "$class_name.lib" );
if ( -e $implib_file ) {
$self->copy_if_modified(
@@ -615,16 +621,12 @@ the Perl bindings for Clownfish modules.
use File::Spec::Functions qw( catdir );
my @cf_base_path = Clownfish::CFC::Perl::Build->cf_base_path;
- my @cf_linker_flags = Clownfish::CFC::Perl::Build->cf_linker_flags(
- 'Other::Module',
- );
my $builder = Clownfish::CFC::Perl::Build->new(
module_name => 'My::Module',
dist_abstract => 'Do something with this and that',
dist_author => 'The Author <au...@example.com>',
dist_version => '0.1.0',
- extra_linker_flags => [ @cf_linker_flags ],
clownfish_params => {
source => [ catdir( @cf_base_path, 'core' ) ],
modules => [
@@ -632,10 +634,12 @@ the Perl bindings for Clownfish modules.
name => 'My::Module',
c_source_dirs => 'xs',
parcels => [ 'MyModule' ],
+ xs_prereqs => [ 'Clownfish' ],
},
{
name => 'My::Module::Test',
parcels => [ 'TestMyModule' ],
+ xs_prereqs => [ 'Clownfish', 'My::Module' ],
},
],
},
@@ -729,14 +733,6 @@ Clownfish .c files.
Returns the base path components of the source tree where C<core> was found.
Currently either C<()> or C<('..')>.
-=head2 cf_linker_flags( I<[module_names]> )
-
- my @flags = Clownfish::CFC::Perl::Build->cf_linker_flags(@module_names);
-
-Returns the linker flags needed to link against all Clownfish modules in
-C<@module_names>. Should be added to C<extra_linker_flags> for all module
-dependencies. Only needed on Windows.
-
=head1 METHODS
=head2 cf_copy_include_file( I<[path components]> )
[12/14] lucy-clownfish git commit: Bump ExtUtils::ParseXS dependency
to 3.00
Posted by nw...@apache.org.
Bump ExtUtils::ParseXS dependency to 3.00
Older versions wouldn't clear the @BootCode global and mess up the
BOOT section when building multiple XS files.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/bad95e07
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/bad95e07
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/bad95e07
Branch: refs/heads/master
Commit: bad95e074b7cf094cf8c06205f7b1c41ddcaa45b
Parents: ef738c2
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 8 13:57:36 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 8 14:35:42 2016 +0200
----------------------------------------------------------------------
compiler/perl/Build.PL | 2 +-
runtime/perl/Build.PL | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bad95e07/compiler/perl/Build.PL
----------------------------------------------------------------------
diff --git a/compiler/perl/Build.PL b/compiler/perl/Build.PL
index 783971f..395478e 100644
--- a/compiler/perl/Build.PL
+++ b/compiler/perl/Build.PL
@@ -31,7 +31,7 @@ my $builder = Clownfish::CFC::Build->new(
build_requires => {
'Module::Build' => 0.280801,
'ExtUtils::CBuilder' => 0.18,
- 'ExtUtils::ParseXS' => 2.16,
+ 'ExtUtils::ParseXS' => 3.00,
'Devel::PPPort' => 3.14,
},
meta_merge => { keywords => [qw( clownfish )], },
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bad95e07/runtime/perl/Build.PL
----------------------------------------------------------------------
diff --git a/runtime/perl/Build.PL b/runtime/perl/Build.PL
index 5190a1e..2178e79 100644
--- a/runtime/perl/Build.PL
+++ b/runtime/perl/Build.PL
@@ -34,7 +34,7 @@ my $builder = Clownfish::Build->new(
build_requires => {
'Module::Build' => 0.280801,
'ExtUtils::CBuilder' => 0.21,
- 'ExtUtils::ParseXS' => 2.18,
+ 'ExtUtils::ParseXS' => 3.00,
'Devel::PPPort' => 3.14,
'Clownfish::CFC' => 0.005000,
},
[02/14] lucy-clownfish git commit: Disable a test in TestClass
Posted by nw...@apache.org.
Disable a test in TestClass
Ivars offsets aren't visible from a separate test binary.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/24fb4d90
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/24fb4d90
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/24fb4d90
Branch: refs/heads/master
Commit: 24fb4d901a56a59913c9ff5a5e67840540215a48
Parents: 83c9045
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 8 13:57:23 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 8 14:25:36 2016 +0200
----------------------------------------------------------------------
runtime/test/Clownfish/Test/TestClass.c | 6 ++++++
1 file changed, 6 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/24fb4d90/runtime/test/Clownfish/Test/TestClass.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestClass.c b/runtime/test/Clownfish/Test/TestClass.c
index a6646f8..b467cd5 100644
--- a/runtime/test/Clownfish/Test/TestClass.c
+++ b/runtime/test/Clownfish/Test/TestClass.c
@@ -59,7 +59,9 @@ static void
test_bootstrap_idempotence(TestBatchRunner *runner) {
Class *bool_class = BOOLEAN;
uint32_t bool_class_size = BOOLEAN->class_alloc_size;
+#if 0
uint32_t bool_ivars_offset = cfish_Bool_IVARS_OFFSET;
+#endif
Boolean *true_singleton = Bool_true_singleton;
char *bool_class_contents = (char*)MALLOCATE(bool_class_size);
@@ -80,8 +82,12 @@ test_bootstrap_idempotence(TestBatchRunner *runner) {
TEST_TRUE(runner,
memcmp(bool_class_contents, BOOLEAN, bool_class_size) == 0,
"Boolean class unchanged");
+#if 0
TEST_TRUE(runner, bool_ivars_offset == cfish_Bool_IVARS_OFFSET,
"Boolean ivars offset unchanged");
+#else
+ SKIP(runner, 1, "TODO: Make ivars offset accessible somehow?");
+#endif
TEST_TRUE(runner, true_singleton == Bool_true_singleton,
"Boolean singleton unchanged");
[11/14] lucy-clownfish git commit: Fix shared library compilation for
Python
Posted by nw...@apache.org.
Fix shared library compilation for Python
Untested. AFAIU, the static library built for Python is linked into
a shared library later. This requires to use -fPIC and define
CFP_CFISH.
I think it would be better if the Python bindings followed the
approach I took for Perl: Pass a list of object files instead of
using a static library.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/3764180f
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/3764180f
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/3764180f
Branch: refs/heads/master
Commit: 3764180f0e7b5893f79d7ecb806b7106dd530b29
Parents: bad95e0
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 8 13:57:39 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 8 14:35:42 2016 +0200
----------------------------------------------------------------------
runtime/common/charmonizer.c | 18 ++++++++++++++++++
runtime/common/charmonizer.main | 18 ++++++++++++++++++
runtime/python/cfext/CFBind.c | 1 +
3 files changed, 37 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3764180f/runtime/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.c b/runtime/common/charmonizer.c
index 37cfaf4..102970e 100644
--- a/runtime/common/charmonizer.c
+++ b/runtime/common/charmonizer.c
@@ -8930,6 +8930,15 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
self->lib
= chaz_MakeFile_add_static_lib(self->makefile, NULL, "clownfish");
lib_objs = "$(CLOWNFISH_STATIC_LIB_OBJS)";
+
+ if (strcmp(host, "python") == 0) {
+ /* For Python, the static library is linked into a shared
+ * library.
+ */
+ compile_flags = chaz_MakeBinary_get_compile_flags(self->lib);
+ chaz_CFlags_compile_shared_library(compile_flags);
+ chaz_CFlags_add_define(compile_flags, "CFP_CFISH", NULL);
+ }
}
if (self->host_src_dir) {
@@ -8967,6 +8976,15 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
self->test_lib
= chaz_MakeFile_add_static_lib(self->makefile, NULL, "testcfish");
test_lib_objs = "$(TESTCFISH_STATIC_LIB_OBJS)";
+
+ if (strcmp(host, "python") == 0) {
+ /* For Python, the static library is linked into a shared
+ * library.
+ */
+ compile_flags = chaz_MakeBinary_get_compile_flags(self->test_lib);
+ chaz_CFlags_compile_shared_library(compile_flags);
+ chaz_CFlags_add_define(compile_flags, "CFP_TESTCFISH", NULL);
+ }
}
chaz_MakeBinary_add_src_dir(self->test_lib, self->test_dir);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3764180f/runtime/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.main b/runtime/common/charmonizer.main
index 124541c..fc68fd4 100644
--- a/runtime/common/charmonizer.main
+++ b/runtime/common/charmonizer.main
@@ -382,6 +382,15 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
self->lib
= chaz_MakeFile_add_static_lib(self->makefile, NULL, "clownfish");
lib_objs = "$(CLOWNFISH_STATIC_LIB_OBJS)";
+
+ if (strcmp(host, "python") == 0) {
+ /* For Python, the static library is linked into a shared
+ * library.
+ */
+ compile_flags = chaz_MakeBinary_get_compile_flags(self->lib);
+ chaz_CFlags_compile_shared_library(compile_flags);
+ chaz_CFlags_add_define(compile_flags, "CFP_CFISH", NULL);
+ }
}
if (self->host_src_dir) {
@@ -419,6 +428,15 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
self->test_lib
= chaz_MakeFile_add_static_lib(self->makefile, NULL, "testcfish");
test_lib_objs = "$(TESTCFISH_STATIC_LIB_OBJS)";
+
+ if (strcmp(host, "python") == 0) {
+ /* For Python, the static library is linked into a shared
+ * library.
+ */
+ compile_flags = chaz_MakeBinary_get_compile_flags(self->test_lib);
+ chaz_CFlags_compile_shared_library(compile_flags);
+ chaz_CFlags_add_define(compile_flags, "CFP_TESTCFISH", NULL);
+ }
}
chaz_MakeBinary_add_src_dir(self->test_lib, self->test_dir);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3764180f/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 4c5780e..0703880 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define CFP_CFISH
#define C_CFISH_OBJ
#define C_CFISH_CLASS
#define C_CFISH_METHOD
[07/14] lucy-clownfish git commit: Move tests to separate directory
Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestVector.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestVector.c b/runtime/core/Clownfish/Test/TestVector.c
deleted file mode 100644
index 17a7f98..0000000
--- a/runtime/core/Clownfish/Test/TestVector.c
+++ /dev/null
@@ -1,572 +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 <stdlib.h>
-
-#define C_CFISH_VECTOR
-#define CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#define MAX_VECTOR_SIZE (SIZE_MAX / sizeof(Obj*))
-
-#include "Clownfish/Test/TestVector.h"
-
-#include "Clownfish/String.h"
-#include "Clownfish/Boolean.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Num.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Vector.h"
-#include "Clownfish/Class.h"
-
-TestVector*
-TestVector_new() {
- return (TestVector*)Class_Make_Obj(TESTVECTOR);
-}
-
-// Return an array of size 10 with 30 garbage pointers behind.
-static Vector*
-S_array_with_garbage() {
- Vector *array = Vec_new(100);
-
- for (int i = 0; i < 40; i++) {
- Vec_Push(array, (Obj*)CFISH_TRUE);
- }
-
- // Remove elements using different methods.
- Vec_Excise(array, 10, 10);
- for (int i = 0; i < 10; i++) { Vec_Pop(array); }
- Vec_Resize(array, 10);
-
- return array;
-}
-
-static void
-test_Equals(TestBatchRunner *runner) {
- Vector *array = Vec_new(0);
- Vector *other = Vec_new(0);
- String *stuff = SSTR_WRAP_C("stuff");
-
- TEST_TRUE(runner, Vec_Equals(array, (Obj*)array),
- "Array equal to self");
-
- TEST_FALSE(runner, Vec_Equals(array, (Obj*)CFISH_TRUE),
- "Array not equal to non-array");
-
- TEST_TRUE(runner, Vec_Equals(array, (Obj*)other),
- "Empty arrays are equal");
-
- Vec_Push(array, (Obj*)CFISH_TRUE);
- TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
- "Add one elem and Equals returns false");
-
- Vec_Push(other, (Obj*)CFISH_TRUE);
- TEST_TRUE(runner, Vec_Equals(array, (Obj*)other),
- "Add a matching elem and Equals returns true");
-
- Vec_Store(array, 2, (Obj*)CFISH_TRUE);
- TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
- "Add elem after a NULL and Equals returns false");
-
- Vec_Store(other, 2, (Obj*)CFISH_TRUE);
- TEST_TRUE(runner, Vec_Equals(array, (Obj*)other),
- "Empty elems don't spoil Equals");
-
- Vec_Store(other, 2, INCREF(stuff));
- TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
- "Non-matching value spoils Equals");
-
- Vec_Store(other, 2, NULL);
- TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
- "NULL value spoils Equals");
- TEST_FALSE(runner, Vec_Equals(other, (Obj*)array),
- "NULL value spoils Equals (reversed)");
-
- Vec_Excise(array, 1, 2); // removes empty elems
- DECREF(Vec_Delete(other, 1)); // leaves NULL in place of deleted elem
- DECREF(Vec_Delete(other, 2));
- TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
- "Empty trailing elements spoil Equals");
-
- DECREF(array);
- DECREF(other);
-}
-
-static void
-test_Store_Fetch(TestBatchRunner *runner) {
- Vector *array = Vec_new(0);
- String *elem;
-
- TEST_TRUE(runner, Vec_Fetch(array, 2) == NULL, "Fetch beyond end");
-
- Vec_Store(array, 2, (Obj*)Str_newf("foo"));
- elem = (String*)CERTIFY(Vec_Fetch(array, 2), STRING);
- TEST_UINT_EQ(runner, 3, Vec_Get_Size(array), "Store updates size");
- TEST_TRUE(runner, Str_Equals_Utf8(elem, "foo", 3), "Store");
-
- elem = (String*)INCREF(elem);
- TEST_INT_EQ(runner, 2, CFISH_REFCOUNT_NN(elem),
- "start with refcount of 2");
- Vec_Store(array, 2, (Obj*)Str_newf("bar"));
- TEST_INT_EQ(runner, 1, CFISH_REFCOUNT_NN(elem),
- "Displacing elem via Store updates refcount");
- DECREF(elem);
- elem = (String*)CERTIFY(Vec_Fetch(array, 2), STRING);
- TEST_TRUE(runner, Str_Equals_Utf8(elem, "bar", 3), "Store displacement");
-
- DECREF(array);
-
- array = S_array_with_garbage();
- Vec_Store(array, 40, (Obj*)CFISH_TRUE);
- bool all_null = true;
- for (size_t i = 10; i < 40; i++) {
- if (Vec_Fetch(array, i) != NULL) { all_null = false; }
- }
- TEST_TRUE(runner, all_null, "Out-of-bounds Store clears excised elements");
- DECREF(array);
-}
-
-static void
-test_Push_Pop_Insert(TestBatchRunner *runner) {
- Vector *array = Vec_new(0);
- String *elem;
-
- TEST_UINT_EQ(runner, Vec_Get_Size(array), 0, "size starts at 0");
- TEST_TRUE(runner, Vec_Pop(array) == NULL,
- "Pop from empty array returns NULL");
-
- Vec_Push(array, (Obj*)Str_newf("a"));
- Vec_Push(array, (Obj*)Str_newf("b"));
- Vec_Push(array, (Obj*)Str_newf("c"));
-
- TEST_UINT_EQ(runner, Vec_Get_Size(array), 3, "size after Push");
- TEST_TRUE(runner, NULL != CERTIFY(Vec_Fetch(array, 2), STRING), "Push");
-
- elem = (String*)CERTIFY(Vec_Pop(array), STRING);
- TEST_TRUE(runner, Str_Equals_Utf8(elem, "c", 1), "Pop");
- TEST_UINT_EQ(runner, Vec_Get_Size(array), 2, "size after Pop");
- DECREF(elem);
-
- Vec_Insert(array, 0, (Obj*)Str_newf("foo"));
- elem = (String*)CERTIFY(Vec_Fetch(array, 0), STRING);
- TEST_TRUE(runner, Str_Equals_Utf8(elem, "foo", 3), "Insert");
- TEST_UINT_EQ(runner, Vec_Get_Size(array), 3, "size after Insert");
-
- for (int i = 0; i < 256; ++i) {
- Vec_Push(array, (Obj*)Str_newf("flotsam"));
- }
- for (size_t i = 0; i < 512; ++i) {
- Vec_Insert(array, i, (Obj*)Str_newf("jetsam"));
- }
- TEST_UINT_EQ(runner, Vec_Get_Size(array), 3 + 256 + 512,
- "size after exercising Push and Insert");
-
- DECREF(array);
-}
-
-static void
-test_Insert_All(TestBatchRunner *runner) {
- int64_t i;
-
- {
- Vector *dst = Vec_new(20);
- Vector *src = Vec_new(10);
- Vector *wanted = Vec_new(30);
-
- for (i = 0; i < 10; i++) { Vec_Push(dst, (Obj*)Int_new(i)); }
- for (i = 0; i < 10; i++) { Vec_Push(dst, (Obj*)Int_new(i + 20)); }
- for (i = 0; i < 10; i++) { Vec_Push(src, (Obj*)Int_new(i + 10)); }
- for (i = 0; i < 30; i++) { Vec_Push(wanted, (Obj*)Int_new(i)); }
-
- Vec_Insert_All(dst, 10, src);
- TEST_TRUE(runner, Vec_Equals(dst, (Obj*)wanted), "Insert_All between");
-
- DECREF(wanted);
- DECREF(src);
- DECREF(dst);
- }
-
- {
- Vector *dst = Vec_new(10);
- Vector *src = Vec_new(10);
- Vector *wanted = Vec_new(30);
-
- for (i = 0; i < 10; i++) { Vec_Push(dst, (Obj*)Int_new(i)); }
- for (i = 0; i < 10; i++) { Vec_Push(src, (Obj*)Int_new(i + 20)); }
- for (i = 0; i < 10; i++) { Vec_Push(wanted, (Obj*)Int_new(i)); }
- for (i = 0; i < 10; i++) {
- Vec_Store(wanted, (size_t)i + 20, (Obj*)Int_new(i + 20));
- }
-
- Vec_Insert_All(dst, 20, src);
- TEST_TRUE(runner, Vec_Equals(dst, (Obj*)wanted), "Insert_All after");
-
- DECREF(wanted);
- DECREF(src);
- DECREF(dst);
- }
-}
-
-static void
-test_Delete(TestBatchRunner *runner) {
- Vector *wanted = Vec_new(5);
- Vector *got = Vec_new(5);
- uint32_t i;
-
- for (i = 0; i < 5; i++) { Vec_Push(got, (Obj*)Str_newf("%u32", i)); }
- Vec_Store(wanted, 0, (Obj*)Str_newf("0", i));
- Vec_Store(wanted, 1, (Obj*)Str_newf("1", i));
- Vec_Store(wanted, 4, (Obj*)Str_newf("4", i));
- DECREF(Vec_Delete(got, 2));
- DECREF(Vec_Delete(got, 3));
- TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got), "Delete");
-
- TEST_TRUE(runner, Vec_Delete(got, 25000) == NULL,
- "Delete beyond array size returns NULL");
-
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_Resize(TestBatchRunner *runner) {
- Vector *array = Vec_new(3);
- uint32_t i;
-
- for (i = 0; i < 2; i++) { Vec_Push(array, (Obj*)Str_newf("%u32", i)); }
- TEST_UINT_EQ(runner, Vec_Get_Capacity(array), 3, "Start with capacity 3");
-
- Vec_Resize(array, 4);
- TEST_UINT_EQ(runner, Vec_Get_Size(array), 4, "Resize up");
- TEST_UINT_EQ(runner, Vec_Get_Capacity(array), 4,
- "Resize changes capacity");
-
- Vec_Resize(array, 2);
- TEST_UINT_EQ(runner, Vec_Get_Size(array), 2, "Resize down");
- TEST_TRUE(runner, Vec_Fetch(array, 2) == NULL, "Resize down zaps elem");
-
- Vec_Resize(array, 2);
- TEST_UINT_EQ(runner, Vec_Get_Size(array), 2, "Resize to same size");
-
- DECREF(array);
-
- array = S_array_with_garbage();
- Vec_Resize(array, 40);
- bool all_null = true;
- for (size_t i = 10; i < 40; i++) {
- if (Vec_Fetch(array, i) != NULL) { all_null = false; }
- }
- TEST_TRUE(runner, all_null, "Resize clears excised elements");
- DECREF(array);
-}
-
-static void
-test_Excise(TestBatchRunner *runner) {
- Vector *wanted = Vec_new(5);
- Vector *got = Vec_new(5);
-
- for (uint32_t i = 0; i < 5; i++) {
- Vec_Push(wanted, (Obj*)Str_newf("%u32", i));
- Vec_Push(got, (Obj*)Str_newf("%u32", i));
- }
-
- Vec_Excise(got, 7, 1);
- TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
- "Excise outside of range is no-op");
-
- Vec_Excise(got, 2, 2);
- DECREF(Vec_Delete(wanted, 2));
- DECREF(Vec_Delete(wanted, 3));
- Vec_Store(wanted, 2, Vec_Delete(wanted, 4));
- Vec_Resize(wanted, 3);
- TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
- "Excise multiple elems");
-
- Vec_Excise(got, 2, 2);
- Vec_Resize(wanted, 2);
- TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
- "Splicing too many elems truncates");
-
- Vec_Excise(got, 0, 1);
- Vec_Store(wanted, 0, Vec_Delete(wanted, 1));
- Vec_Resize(wanted, 1);
- TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
- "Excise first elem");
-
- DECREF(got);
- DECREF(wanted);
-}
-
-static void
-test_Push_All(TestBatchRunner *runner) {
- Vector *wanted = Vec_new(0);
- Vector *got = Vec_new(0);
- Vector *scratch = Vec_new(0);
- Vector *empty = Vec_new(0);
- uint32_t i;
-
- for (i = 0; i < 40; i++) { Vec_Push(wanted, (Obj*)Str_newf("%u32", i)); }
- Vec_Push(wanted, NULL);
- for (i = 0; i < 20; i++) { Vec_Push(got, (Obj*)Str_newf("%u32", i)); }
- for (i = 20; i < 40; i++) { Vec_Push(scratch, (Obj*)Str_newf("%u32", i)); }
- Vec_Push(scratch, NULL);
-
- Vec_Push_All(got, scratch);
- TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got), "Push_All");
-
- Vec_Push_All(got, empty);
- TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
- "Push_All with empty array");
-
- DECREF(wanted);
- DECREF(got);
- DECREF(scratch);
- DECREF(empty);
-}
-
-static void
-test_Slice(TestBatchRunner *runner) {
- Vector *array = Vec_new(0);
- for (uint32_t i = 0; i < 10; i++) { Vec_Push(array, (Obj*)Str_newf("%u32", i)); }
- {
- Vector *slice = Vec_Slice(array, 0, 10);
- TEST_TRUE(runner, Vec_Equals(array, (Obj*)slice), "Slice entire array");
- DECREF(slice);
- }
- {
- Vector *slice = Vec_Slice(array, 0, 11);
- TEST_TRUE(runner, Vec_Equals(array, (Obj*)slice),
- "Exceed length");
- DECREF(slice);
- }
- {
- Vector *wanted = Vec_new(0);
- Vec_Push(wanted, (Obj*)Str_newf("9"));
- Vector *slice = Vec_Slice(array, 9, 11);
- TEST_TRUE(runner, Vec_Equals(slice, (Obj*)wanted),
- "Exceed length, start near end");
- DECREF(slice);
- DECREF(wanted);
- }
- {
- Vector *slice = Vec_Slice(array, 0, 0);
- TEST_TRUE(runner, Vec_Get_Size(slice) == 0, "empty slice");
- DECREF(slice);
- }
- {
- Vector *slice = Vec_Slice(array, 20, 1);
- TEST_TRUE(runner, Vec_Get_Size(slice) == 0, "exceed offset");
- DECREF(slice);
- }
- {
- Vector *wanted = Vec_new(0);
- Vec_Push(wanted, (Obj*)Str_newf("9"));
- Vector *slice = Vec_Slice(array, 9, SIZE_MAX - 1);
- TEST_TRUE(runner, Vec_Get_Size(slice) == 1, "guard against overflow");
- DECREF(slice);
- DECREF(wanted);
- }
- DECREF(array);
-}
-
-static void
-test_Clone(TestBatchRunner *runner) {
- Vector *array = Vec_new(0);
- Vector *twin;
- uint32_t i;
-
- for (i = 0; i < 10; i++) {
- Vec_Push(array, (Obj*)Int_new(i));
- }
- Vec_Push(array, NULL);
- twin = Vec_Clone(array);
- TEST_TRUE(runner, Vec_Equals(array, (Obj*)twin), "Clone");
- TEST_TRUE(runner, Vec_Fetch(array, 1) == Vec_Fetch(twin, 1),
- "Clone doesn't clone elements");
-
- DECREF(array);
- DECREF(twin);
-}
-
-static void
-S_push(void *context) {
- Vector *vec = (Vector*)context;
- Vec_Push(vec, (Obj*)CFISH_TRUE);
-}
-
-static void
-S_insert_at_size_max(void *context) {
- Vector *vec = (Vector*)context;
- Vec_Insert(vec, SIZE_MAX, (Obj*)CFISH_TRUE);
-}
-
-static void
-S_store_at_size_max(void *context) {
- Vector *vec = (Vector*)context;
- Vec_Store(vec, SIZE_MAX, (Obj*)CFISH_TRUE);
-}
-
-typedef struct {
- Vector *vec;
- Vector *other;
-} VectorPair;
-
-static void
-S_push_all(void *vcontext) {
- VectorPair *context = (VectorPair*)vcontext;
- Vec_Push_All(context->vec, context->other);
-}
-
-static void
-S_insert_all_at_size_max(void *vcontext) {
- VectorPair *context = (VectorPair*)vcontext;
- Vec_Insert_All(context->vec, SIZE_MAX, context->other);
-}
-
-static void
-S_test_exception(TestBatchRunner *runner, Err_Attempt_t func, void *context,
- const char *test_name) {
- Err *error = Err_trap(func, context);
- TEST_TRUE(runner, error != NULL, test_name);
- DECREF(error);
-}
-
-static void
-test_exceptions(TestBatchRunner *runner) {
- {
- Vector *vec = Vec_new(0);
- vec->cap = MAX_VECTOR_SIZE;
- vec->size = vec->cap;
- S_test_exception(runner, S_push, vec, "Push throws on overflow");
- vec->size = 0;
- DECREF(vec);
- }
-
- {
- Vector *vec = Vec_new(0);
- S_test_exception(runner, S_insert_at_size_max, vec,
- "Insert throws on overflow");
- DECREF(vec);
- }
-
- {
- Vector *vec = Vec_new(0);
- S_test_exception(runner, S_store_at_size_max, vec,
- "Store throws on overflow");
- DECREF(vec);
- }
-
- {
- VectorPair context;
- context.vec = Vec_new(0);
- context.vec->cap = 1000000000;
- context.vec->size = context.vec->cap;
- context.other = Vec_new(0);
- context.other->cap = MAX_VECTOR_SIZE - context.vec->cap + 1;
- context.other->size = context.other->cap;
- S_test_exception(runner, S_push_all, &context,
- "Push_All throws on overflow");
- context.vec->size = 0;
- context.other->size = 0;
- DECREF(context.other);
- DECREF(context.vec);
- }
-
- {
- VectorPair context;
- context.vec = Vec_new(0);
- context.other = Vec_new(0);
- S_test_exception(runner, S_insert_all_at_size_max, &context,
- "Insert_All throws on overflow");
- DECREF(context.other);
- DECREF(context.vec);
- }
-}
-
-static void
-test_Sort(TestBatchRunner *runner) {
- Vector *array = Vec_new(8);
- Vector *wanted = Vec_new(8);
-
- Vec_Push(array, NULL);
- Vec_Push(array, (Obj*)Str_newf("aaab"));
- Vec_Push(array, (Obj*)Str_newf("ab"));
- Vec_Push(array, NULL);
- Vec_Push(array, NULL);
- Vec_Push(array, (Obj*)Str_newf("aab"));
- Vec_Push(array, (Obj*)Str_newf("b"));
-
- Vec_Push(wanted, (Obj*)Str_newf("aaab"));
- Vec_Push(wanted, (Obj*)Str_newf("aab"));
- Vec_Push(wanted, (Obj*)Str_newf("ab"));
- Vec_Push(wanted, (Obj*)Str_newf("b"));
- Vec_Push(wanted, NULL);
- Vec_Push(wanted, NULL);
- Vec_Push(wanted, NULL);
-
- Vec_Sort(array);
- TEST_TRUE(runner, Vec_Equals(array, (Obj*)wanted), "Sort with NULLs");
-
- DECREF(array);
- DECREF(wanted);
-}
-
-static void
-test_Grow(TestBatchRunner *runner) {
- Vector *array = Vec_new(500);
- size_t cap;
-
- cap = Vec_Get_Capacity(array);
- TEST_TRUE(runner, cap >= 500, "Array is created with minimum capacity");
-
- Vec_Grow(array, 2000);
- cap = Vec_Get_Capacity(array);
- TEST_TRUE(runner, cap >= 2000, "Grow to larger capacity");
-
- size_t old_cap = cap;
- Vec_Grow(array, old_cap);
- cap = Vec_Get_Capacity(array);
- TEST_TRUE(runner, cap >= old_cap, "Grow to same capacity");
-
- Vec_Grow(array, 1000);
- cap = Vec_Get_Capacity(array);
- TEST_TRUE(runner, cap >= 1000, "Grow to smaller capacity");
-
- DECREF(array);
-}
-
-void
-TestVector_Run_IMP(TestVector *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 62);
- test_Equals(runner);
- test_Store_Fetch(runner);
- test_Push_Pop_Insert(runner);
- test_Insert_All(runner);
- test_Delete(runner);
- test_Resize(runner);
- test_Excise(runner);
- test_Push_All(runner);
- test_Slice(runner);
- test_Clone(runner);
- test_exceptions(runner);
- test_Sort(runner);
- test_Grow(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestVector.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestVector.cfh b/runtime/core/Clownfish/Test/TestVector.cfh
deleted file mode 100644
index 090b8b9..0000000
--- a/runtime/core/Clownfish/Test/TestVector.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::TestVector
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestVector*
- new();
-
- void
- Run(TestVector *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/Util/TestAtomic.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/Util/TestAtomic.c b/runtime/core/Clownfish/Test/Util/TestAtomic.c
deleted file mode 100644
index f87279a..0000000
--- a/runtime/core/Clownfish/Test/Util/TestAtomic.c
+++ /dev/null
@@ -1,65 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/Util/TestAtomic.h"
-
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/Util/Atomic.h"
-#include "Clownfish/Class.h"
-
-TestAtomic*
-TestAtomic_new() {
- return (TestAtomic*)Class_Make_Obj(TESTATOMIC);
-}
-
-static void
-test_cas_ptr(TestBatchRunner *runner) {
- int foo = 1;
- int bar = 2;
- int *foo_pointer = &foo;
- int *bar_pointer = &bar;
- int *target = NULL;
-
- TEST_TRUE(runner,
- Atomic_cas_ptr((void**)&target, NULL, foo_pointer),
- "cas_ptr returns true on success");
- TEST_TRUE(runner, target == foo_pointer, "cas_ptr sets target");
-
- target = NULL;
- 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(runner, target == NULL,
- "cas_ptr doesn't do anything to target when old_value doesn't match");
-
- target = foo_pointer;
- TEST_TRUE(runner,
- Atomic_cas_ptr((void**)&target, foo_pointer, bar_pointer),
- "cas_ptr from one value to another");
- TEST_TRUE(runner, target == bar_pointer, "cas_ptr sets target");
-}
-
-void
-TestAtomic_Run_IMP(TestAtomic *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
- test_cas_ptr(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/Util/TestAtomic.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/Util/TestAtomic.cfh b/runtime/core/Clownfish/Test/Util/TestAtomic.cfh
deleted file mode 100644
index 2788342..0000000
--- a/runtime/core/Clownfish/Test/Util/TestAtomic.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::Util::TestAtomic
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestAtomic*
- new();
-
- void
- Run(TestAtomic *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/Util/TestMemory.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/Util/TestMemory.c b/runtime/core/Clownfish/Test/Util/TestMemory.c
deleted file mode 100644
index 8151c72..0000000
--- a/runtime/core/Clownfish/Test/Util/TestMemory.c
+++ /dev/null
@@ -1,119 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "charmony.h"
-
-#include "Clownfish/Test/Util/TestMemory.h"
-
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/Util/Memory.h"
-#include "Clownfish/Class.h"
-
-TestMemory*
-TestMemory_new() {
- return (TestMemory*)Class_Make_Obj(TESTMEMORY);
-}
-
-static void
-test_oversize__growth_rate(TestBatchRunner *runner) {
- 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(runner, "Asked for %" PRId64 ", got smaller amount %" PRId64,
- size + 1, next_size);
- break;
- }
- if (size > 0) {
- growth_count += 1;
- double growth_rate = CHY_U64_TO_DOUBLE(next_size) /
- CHY_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(runner, "Average growth rate dropped below 1.1x: %f",
- average_growth_rate);
- success = false;
- break;
- }
- }
- size = next_size;
- }
- TEST_TRUE(runner, growth_count > 0, "Grew %f times", growth_count);
- if (success) {
- TEST_TRUE(runner, average_growth_rate > 1.1,
- "Growth rate of oversize() averages above 1.1: %.3f",
- average_growth_rate);
- }
-
- for (size_t minimum = 1; minimum < 8; minimum++) {
- uint64_t next_size = Memory_oversize(minimum, sizeof(void*));
- double growth_rate = CHY_U64_TO_DOUBLE(next_size) / (double)minimum;
- TEST_TRUE(runner, growth_rate > 1.2,
- "Growth rate is higher for smaller arrays (%u, %.3f)",
- (unsigned)minimum, growth_rate);
- }
-}
-
-static void
-test_oversize__ceiling(TestBatchRunner *runner) {
- for (unsigned width = 0; width < 10; width++) {
- size_t size = Memory_oversize(SIZE_MAX, width);
- TEST_TRUE(runner, size == SIZE_MAX,
- "Memory_oversize hits ceiling at SIZE_MAX (width %u)", width);
- size = Memory_oversize(SIZE_MAX - 1, width);
- TEST_TRUE(runner, size == SIZE_MAX,
- "Memory_oversize hits ceiling at SIZE_MAX (width %u)", width);
- }
-}
-
-static void
-test_oversize__rounding(TestBatchRunner *runner) {
- unsigned widths[] = { 1, 2, 4, 0 };
-
- for (int width_tick = 0; widths[width_tick] != 0; width_tick++) {
- unsigned width = widths[width_tick];
- for (unsigned i = 0; i < 25; i++) {
- size_t size = Memory_oversize(i, width);
- size_t bytes = size * width;
- if (bytes % sizeof(size_t) != 0) {
- FAIL(runner, "Rounding failure for %u, width %u",
- i, width);
- return;
- }
- }
- }
- PASS(runner, "Round allocations up to the size of a pointer");
-}
-
-void
-TestMemory_Run_IMP(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-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/Util/TestMemory.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/Util/TestMemory.cfh b/runtime/core/Clownfish/Test/Util/TestMemory.cfh
deleted file mode 100644
index d0b5803..0000000
--- a/runtime/core/Clownfish/Test/Util/TestMemory.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::Util::TestMemory
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestMemory*
- new();
-
- void
- Run(TestMemory *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/Util/TestStringHelper.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/Util/TestStringHelper.c b/runtime/core/Clownfish/Test/Util/TestStringHelper.c
deleted file mode 100644
index 2a873fd..0000000
--- a/runtime/core/Clownfish/Test/Util/TestStringHelper.c
+++ /dev/null
@@ -1,373 +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>
-
-#define CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/Util/TestStringHelper.h"
-
-#include "Clownfish/String.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/Util/StringHelper.h"
-#include "Clownfish/Class.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() {
- return (TestStringHelper*)Class_Make_Obj(TESTSTRINGHELPER);
-}
-
-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(TestBatchRunner *runner) {
- size_t result;
- result = StrHelp_overlap("", "", 0, 0);
- TEST_UINT_EQ(runner, result, 0, "two empty strings");
- result = StrHelp_overlap("", "foo", 0, 3);
- TEST_UINT_EQ(runner, result, 0, "first string is empty");
- result = StrHelp_overlap("foo", "", 3, 0);
- TEST_UINT_EQ(runner, result, 0, "second string is empty");
- result = StrHelp_overlap("foo", "foo", 3, 3);
- TEST_UINT_EQ(runner, result, 3, "equal strings");
- result = StrHelp_overlap("foo bar", "foo", 7, 3);
- TEST_UINT_EQ(runner, result, 3, "first string is longer");
- result = StrHelp_overlap("foo", "foo bar", 3, 7);
- TEST_UINT_EQ(runner, result, 3, "second string is longer");
- result = StrHelp_overlap("bar", "baz", 3, 3);
- TEST_UINT_EQ(runner, result, 2, "different byte");
-}
-
-
-static void
-test_to_base36(TestBatchRunner *runner) {
- char buffer[StrHelp_MAX_BASE36_BYTES];
- StrHelp_to_base36(UINT64_MAX, buffer);
- TEST_STR_EQ(runner, "3w5e11264sgsf", buffer, "base36 UINT64_MAX");
- StrHelp_to_base36(1, buffer);
- TEST_STR_EQ(runner, "1", buffer, "base36 1");
- TEST_INT_EQ(runner, buffer[1], 0, "base36 NULL termination");
-}
-
-static void
-test_utf8_round_trip(TestBatchRunner *runner) {
- int32_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(runner, "Successfully round tripped 0 - 0x10FFFF");
- }
- else {
- FAIL(runner, "Failed round trip at 0x%.1X", (unsigned)code_point);
- }
-}
-
-static void
-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(runner, "Disagreement: %s", description);
- }
- else {
- TEST_TRUE(runner, sane == expected, "%s", description);
- }
-}
-
-static void
-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(runner, "\xF0\x9D\x84\x9E", 4, true,
- "Musical symbol G clef");
- S_test_validity(runner, "\xED\xA0\xB4\xED\xB4\x9E", 6, false,
- "G clef as UTF-8 encoded UTF-16 surrogates");
- S_test_validity(runner, ".\xED\xA0\xB4.", 5, false,
- "Isolated high surrogate");
- S_test_validity(runner, ".\xED\xB4\x9E.", 5, false,
- "Isolated low surrogate");
-
- // Shortest form.
- S_test_validity(runner, ".\xC1\x9C.", 4, false,
- "Non-shortest form ASCII backslash");
- S_test_validity(runner, ".\xC0\xAF.", 4, false,
- "Non-shortest form ASCII slash");
- S_test_validity(runner, ".\xC0\x80.", 4, false,
- "Non-shortest form ASCII NUL character");
- S_test_validity(runner, ".\xE0\x9F\xBF.", 5, false,
- "Non-shortest form three byte sequence");
- S_test_validity(runner, ".\xF0\x8F\xBF\xBF.", 6, false,
- "Non-shortest form four byte sequence");
-
- // Range.
- S_test_validity(runner, "\xF8\x88\x80\x80\x80", 5, false, "5-byte UTF-8");
- S_test_validity(runner, "\xF4\x8F\xBF\xBF", 4, true,
- "Code point 0x10FFFF");
- S_test_validity(runner, "\xF4\x90\x80\x80", 4, false,
- "Code point 0x110000 too large");
- S_test_validity(runner, "\xF5\x80\x80\x80", 4, false,
- "Sequence starting with 0xF5");
-
- // Truncated sequences.
- S_test_validity(runner, "\xC2", 1, false,
- "Truncated two byte sequence");
- S_test_validity(runner, "\xE2\x98", 2, false,
- "Truncated three byte sequence");
- S_test_validity(runner, "\xF0\x9D\x84", 3, false,
- "Truncated four byte sequence");
-
- // Bad continuations.
- S_test_validity(runner, "\xE2\x98\xBA\xE2\x98\xBA", 6, true,
- "SmileySmiley");
- S_test_validity(runner, "\xE2\xBA\xE2\x98\xBA", 5, false,
- "missing first continuation byte");
- S_test_validity(runner, "\xE2\x98\xE2\x98\xBA", 5, false,
- "missing second continuation byte");
- S_test_validity(runner, "\xE2\xE2\x98\xBA", 4, false,
- "missing both continuation bytes");
- S_test_validity(runner, "\xBA\xE2\x98\xBA\xE2\xBA", 5, false,
- "missing first continuation byte (end)");
- S_test_validity(runner, "\xE2\x98\xBA\xE2\x98", 5, false,
- "missing second continuation byte (end)");
- S_test_validity(runner, "\xE2\x98\xBA\xE2", 4, false,
- "missing both continuation bytes (end)");
- S_test_validity(runner, "\xBA\xE2\x98\xBA", 4, false,
- "isolated continuation byte 0xBA");
- S_test_validity(runner, "\x98\xE2\x98\xBA", 4, false,
- "isolated continuation byte 0x98");
- S_test_validity(runner, "\xE2\x98\xBA\xBA", 4, false,
- "isolated continuation byte 0xBA (end)");
- S_test_validity(runner, "\xE2\x98\xBA\x98", 4, false,
- "isolated continuation byte 0x98 (end)");
- S_test_validity(runner, "\xF0xxxx", 5, false,
- "missing continuation byte 2/4");
- S_test_validity(runner, "\xF0\x9Dxxxx", 5, false,
- "missing continuation byte 3/4");
- S_test_validity(runner, "\xF0\x9D\x84xx", 5, false,
- "missing continuation byte 4/4");
-}
-
-static void
-S_validate_utf8(void *context) {
- const char *text = (const char*)context;
- StrHelp_validate_utf8(text, strlen(text), "src.c", 17, "fn");
-}
-
-static void
-test_validate_utf8(TestBatchRunner *runner) {
- {
- Err *error = Err_trap(S_validate_utf8, "Sigma\xC1\x9C.");
- TEST_TRUE(runner, error != NULL, "validate_utf8 throws");
- String *mess = Err_Get_Mess(error);
- const char *expected = "Invalid UTF-8 after 'Sigma': C1 9C 2E\n";
- bool ok = Str_Starts_With_Utf8(mess, expected, strlen(expected));
- TEST_TRUE(runner, ok, "validate_utf8 throws correct error message");
- DECREF(error);
- }
-
- {
- Err *error = Err_trap(S_validate_utf8,
- "xxx123456789\xE2\x93\xAA"
- "1234567890\xC1\x9C.");
- String *mess = Err_Get_Mess(error);
- const char *expected =
- "Invalid UTF-8 after '123456789\xE2\x93\xAA"
- "1234567890': C1 9C 2E\n";
- bool ok = Str_Starts_With_Utf8(mess, expected, strlen(expected));
- TEST_TRUE(runner, ok, "validate_utf8 truncates long prefix");
- DECREF(error);
- }
-}
-
-static void
-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_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
-S_encode_utf8_char(void *context) {
- int32_t *code_point_ptr = (int32_t*)context;
- char buffer[4];
- StrHelp_encode_utf8_char(*code_point_ptr, buffer);
-}
-
-static void
-test_encode_utf8_char(TestBatchRunner *runner) {
- int32_t code_point = 0x110000;
- Err *error = Err_trap(S_encode_utf8_char, &code_point);
- TEST_TRUE(runner, error != NULL, "Encode code point 0x110000 throws");
- DECREF(error);
-}
-
-static void
-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(runner, StrHelp_back_utf8_char(end, buffer) == buffer,
- "back_utf8_char");
- TEST_TRUE(runner, StrHelp_back_utf8_char(end, buf) == NULL,
- "back_utf8_char returns NULL rather than back up beyond start");
- TEST_TRUE(runner, StrHelp_back_utf8_char(buffer, buffer) == NULL,
- "back_utf8_char returns NULL when end == start");
-}
-
-void
-TestStrHelp_Run_IMP(TestStringHelper *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 55);
- test_overlap(runner);
- test_to_base36(runner);
- test_utf8_round_trip(runner);
- test_utf8_valid(runner);
- test_validate_utf8(runner);
- test_is_whitespace(runner);
- test_encode_utf8_char(runner);
- test_back_utf8_char(runner);
-}
-
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/Util/TestStringHelper.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/Util/TestStringHelper.cfh b/runtime/core/Clownfish/Test/Util/TestStringHelper.cfh
deleted file mode 100644
index 752c553..0000000
--- a/runtime/core/Clownfish/Test/Util/TestStringHelper.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::Util::TestStringHelper nickname TestStrHelp
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestStringHelper*
- new();
-
- void
- Run(TestStringHelper *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/TestClownfish.c
----------------------------------------------------------------------
diff --git a/runtime/core/TestClownfish.c b/runtime/core/TestClownfish.c
deleted file mode 100644
index e9ec7a3..0000000
--- a/runtime/core/TestClownfish.c
+++ /dev/null
@@ -1,22 +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 "testcfish_parcel.h"
-
-void
-testcfish_init_parcel() {
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/TestClownfish.cfp
----------------------------------------------------------------------
diff --git a/runtime/core/TestClownfish.cfp b/runtime/core/TestClownfish.cfp
deleted file mode 100644
index 6db4b4a..0000000
--- a/runtime/core/TestClownfish.cfp
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "TestClownfish",
- "nickname": "TestCfish",
- "version": "v0.5.0",
- "prerequisites": {
- "Clownfish": "v0.5.0"
- }
-}
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/go/build.go
----------------------------------------------------------------------
diff --git a/runtime/go/build.go b/runtime/go/build.go
index 6b0b0be..c6eb9e3 100644
--- a/runtime/go/build.go
+++ b/runtime/go/build.go
@@ -119,6 +119,7 @@ func configure() {
func runCFC() {
hierarchy := cfc.NewHierarchy("autogen")
hierarchy.AddSourceDir("../core")
+ hierarchy.AddSourceDir("../test")
hierarchy.Build()
autogenHeader := "Auto-generated by build.go.\n"
coreBinding := cfc.NewBindCore(hierarchy, autogenHeader, "")
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/perl/buildlib/Clownfish/Build.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/buildlib/Clownfish/Build.pm b/runtime/perl/buildlib/Clownfish/Build.pm
index 9506662..81b5fbf 100644
--- a/runtime/perl/buildlib/Clownfish/Build.pm
+++ b/runtime/perl/buildlib/Clownfish/Build.pm
@@ -54,13 +54,16 @@ my $XS_SOURCE_DIR = 'xs';
my $CFC_BUILD = catfile( $CFC_DIR, 'Build' );
my $LIB_DIR = 'lib';
my $CORE_SOURCE_DIR;
+my $TEST_SOURCE_DIR;
my $CHARMONIZER_C;
if ($IS_CPAN_DIST) {
$CORE_SOURCE_DIR = 'cfcore';
+ $TEST_SOURCE_DIR = 'cftest';
$CHARMONIZER_C = 'charmonizer.c';
}
else {
$CORE_SOURCE_DIR = catdir( @BASE_PATH, 'core' );
+ $TEST_SOURCE_DIR = catdir( @BASE_PATH, 'test' );
$CHARMONIZER_C = catfile( $COMMON_SOURCE_DIR, 'charmonizer.c' );
}
@@ -70,7 +73,7 @@ sub new {
$args{clownfish_params} = {
autogen_header => _autogen_header(),
include => [], # Don't use default includes.
- source => [ $CORE_SOURCE_DIR ],
+ source => [ $CORE_SOURCE_DIR, $TEST_SOURCE_DIR ],
modules => [
{
name => 'Clownfish',
@@ -317,6 +320,7 @@ sub ACTION_dist {
'../../NOTICE' => 'NOTICE',
'../../README.md' => 'README.md',
$CORE_SOURCE_DIR => 'cfcore',
+ $TEST_SOURCE_DIR => 'cftest',
$CHARMONIZER_C => 'charmonizer.c',
);
print "Copying files...\n";
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/python/setup.py
----------------------------------------------------------------------
diff --git a/runtime/python/setup.py b/runtime/python/setup.py
index fa184ef..717ce50 100644
--- a/runtime/python/setup.py
+++ b/runtime/python/setup.py
@@ -51,6 +51,7 @@ make_command = "make" # TODO portability
BASE_DIR = os.path.abspath(os.path.join(os.pardir, os.pardir))
PARENT_DIR = os.path.abspath(os.pardir)
CORE_SOURCE_DIR = os.path.join(PARENT_DIR, 'core')
+TEST_SOURCE_DIR = os.path.join(PARENT_DIR, 'test')
CFEXT_DIR = 'cfext'
COMMON_SOURCE_DIR = os.path.join(PARENT_DIR, 'common')
CHARMONIZER_C = os.path.join(COMMON_SOURCE_DIR, 'charmonizer.c')
@@ -133,6 +134,7 @@ class libclownfish(_Command):
import cfc
hierarchy = cfc.model.Hierarchy(dest="autogen")
hierarchy.add_source_dir(CORE_SOURCE_DIR)
+ hierarchy.add_source_dir(TEST_SOURCE_DIR)
hierarchy.build()
header = "Autogenerated by setup.py"
core_binding = cfc.binding.BindCore(hierarchy=hierarchy, header=header)
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test.c b/runtime/test/Clownfish/Test.c
new file mode 100644
index 0000000..4ae6163
--- /dev/null
+++ b/runtime/test/Clownfish/Test.c
@@ -0,0 +1,70 @@
+/* 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.h"
+
+#include "Clownfish/TestHarness/TestBatch.h"
+#include "Clownfish/TestHarness/TestSuite.h"
+
+#include "Clownfish/Test/TestBlob.h"
+#include "Clownfish/Test/TestBoolean.h"
+#include "Clownfish/Test/TestByteBuf.h"
+#include "Clownfish/Test/TestString.h"
+#include "Clownfish/Test/TestCharBuf.h"
+#include "Clownfish/Test/TestClass.h"
+#include "Clownfish/Test/TestErr.h"
+#include "Clownfish/Test/TestHash.h"
+#include "Clownfish/Test/TestHashIterator.h"
+#include "Clownfish/Test/TestLockFreeRegistry.h"
+#include "Clownfish/Test/TestMethod.h"
+#include "Clownfish/Test/TestNum.h"
+#include "Clownfish/Test/TestObj.h"
+#include "Clownfish/Test/TestPtrHash.h"
+#include "Clownfish/Test/TestVector.h"
+#include "Clownfish/Test/Util/TestAtomic.h"
+#include "Clownfish/Test/Util/TestMemory.h"
+#include "Clownfish/Test/Util/TestStringHelper.h"
+
+TestSuite*
+Test_create_test_suite() {
+ TestSuite *suite = TestSuite_new();
+
+ TestSuite_Add_Batch(suite, (TestBatch*)TestClass_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestMethod_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestVector_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestHash_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestHashIterator_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestObj_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestErr_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestBlob_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestBB_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestStr_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestCB_new());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestBoolean_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());
+ TestSuite_Add_Batch(suite, (TestBatch*)TestPtrHash_new());
+
+ return suite;
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test.cfh b/runtime/test/Clownfish/Test.cfh
new file mode 100644
index 0000000..68dc8bc
--- /dev/null
+++ b/runtime/test/Clownfish/Test.cfh
@@ -0,0 +1,26 @@
+/* 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;
+
+/** Clownfish test suite.
+ */
+inert class Clownfish::Test {
+ inert incremented TestSuite*
+ create_test_suite();
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestBlob.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestBlob.c b/runtime/test/Clownfish/Test/TestBlob.c
new file mode 100644
index 0000000..5776f47
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestBlob.c
@@ -0,0 +1,147 @@
+/* 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/TestBlob.h"
+
+#include "Clownfish/Blob.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Class.h"
+#include "Clownfish/Util/Memory.h"
+
+#include <string.h>
+
+TestBlob*
+TestBlob_new() {
+ return (TestBlob*)Class_Make_Obj(TESTBLOB);
+}
+
+static void
+test_new_steal(TestBatchRunner *runner) {
+ size_t size = 4;
+ char *buf = (char*)MALLOCATE(size);
+ memset(buf, 'x', size);
+ Blob *blob = Blob_new_steal(buf, size);
+ TEST_TRUE(runner, Blob_Get_Buf(blob) == buf, "new_steal steals buf");
+ TEST_TRUE(runner, Blob_Equals_Bytes(blob, "xxxx", 4),
+ "new_steal doesn't change buf");
+ DECREF(blob);
+}
+
+static void
+test_new_wrap(TestBatchRunner *runner) {
+ static const char buf[] = "xxxx";
+ Blob *blob = Blob_new_wrap(buf, 4);
+ TEST_TRUE(runner, Blob_Get_Buf(blob) == buf, "new_wrap wraps buf");
+ TEST_TRUE(runner, Blob_Equals_Bytes(blob, "xxxx", 4),
+ "new_wrap doesn't change buf");
+ DECREF(blob);
+}
+
+static void
+test_Equals(TestBatchRunner *runner) {
+ Blob *blob = Blob_new("foo", 4); // Include terminating NULL.
+
+ {
+ Blob *other = Blob_new("foo", 4);
+ TEST_TRUE(runner, Blob_Equals(blob, (Obj*)other), "Equals");
+ DECREF(other);
+ }
+
+ {
+ Blob *other = Blob_new("foo", 3);
+ TEST_FALSE(runner, Blob_Equals(blob, (Obj*)other),
+ "Different size spoils Equals");
+ DECREF(other);
+ }
+
+ {
+ Blob *other = Blob_new("bar", 4);
+ TEST_UINT_EQ(runner, Blob_Get_Size(blob), Blob_Get_Size(other),
+ "same length");
+ TEST_FALSE(runner, Blob_Equals(blob, (Obj*)other),
+ "Different content spoils Equals");
+ DECREF(other);
+ }
+
+ TEST_FALSE(runner, Blob_Equals(blob, (Obj*)BLOB),
+ "Different type spoils Equals");
+
+ TEST_TRUE(runner, Blob_Equals_Bytes(blob, "foo", 4), "Equals_Bytes");
+ TEST_FALSE(runner, Blob_Equals_Bytes(blob, "foo", 3),
+ "Equals_Bytes spoiled by different size");
+ TEST_FALSE(runner, Blob_Equals_Bytes(blob, "bar", 4),
+ "Equals_Bytes spoiled by different content");
+
+ DECREF(blob);
+}
+
+static void
+test_Clone(TestBatchRunner *runner) {
+ Blob *blob = Blob_new("foo", 3);
+ Blob *twin = Blob_Clone(blob);
+ TEST_TRUE(runner, Blob_Equals(blob, (Obj*)twin), "Clone");
+ DECREF(blob);
+ DECREF(twin);
+}
+
+static void
+test_Compare_To(TestBatchRunner *runner) {
+ {
+ Blob *a = Blob_new("foo", 4);
+ Blob *b = Blob_new("foo", 4);
+ TEST_INT_EQ(runner, Blob_Compare_To(a, (Obj*)b), 0,
+ "Compare_To returns 0 for equal Blobs");
+ DECREF(a);
+ DECREF(b);
+ }
+
+ {
+ Blob *a = Blob_new("foo", 3);
+ Blob *b = Blob_new("foo\0b", 5);
+ TEST_TRUE(runner, Blob_Compare_To(a, (Obj*)b) < 0,
+ "shorter Blob sorts first");
+ TEST_TRUE(runner, Blob_Compare_To(b, (Obj*)a) > 0,
+ "longer Blob sorts last");
+ DECREF(a);
+ DECREF(b);
+ }
+
+ {
+ Blob *a = Blob_new("foo\0a", 5);
+ Blob *b = Blob_new("foo\0b", 5);
+ TEST_TRUE(runner, Blob_Compare_To(a, (Obj*)b) < 0,
+ "NULL doesn't interfere with Compare_To");
+ DECREF(a);
+ DECREF(b);
+ }
+}
+
+void
+TestBlob_Run_IMP(TestBlob *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 17);
+ test_new_steal(runner);
+ test_new_wrap(runner);
+ test_Equals(runner);
+ test_Clone(runner);
+ test_Compare_To(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestBlob.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestBlob.cfh b/runtime/test/Clownfish/Test/TestBlob.cfh
new file mode 100644
index 0000000..4d3d4b6
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestBlob.cfh
@@ -0,0 +1,28 @@
+/* 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::TestBlob inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestBlob*
+ new();
+
+ void
+ Run(TestBlob *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestBoolean.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestBoolean.c b/runtime/test/Clownfish/Test/TestBoolean.c
new file mode 100644
index 0000000..8835fe1
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestBoolean.c
@@ -0,0 +1,99 @@
+/* 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/TestBoolean.h"
+
+#include "Clownfish/String.h"
+#include "Clownfish/Boolean.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Class.h"
+
+TestBoolean*
+TestBoolean_new() {
+ return (TestBoolean*)Class_Make_Obj(TESTBOOLEAN);
+}
+
+static void
+test_singleton(TestBatchRunner *runner) {
+ TEST_TRUE(runner, Bool_singleton(true) == CFISH_TRUE,
+ "Bool_singleton true");
+ TEST_TRUE(runner, Bool_singleton(false) == CFISH_FALSE,
+ "Bool_singleton false");
+}
+
+static void
+test_To_String(TestBatchRunner *runner) {
+ String *true_string = Bool_To_String(CFISH_TRUE);
+ String *false_string = Bool_To_String(CFISH_FALSE);
+
+ TEST_TRUE(runner, Str_Equals_Utf8(true_string, "true", 4),
+ "Bool_To_String [true]");
+ TEST_TRUE(runner, Str_Equals_Utf8(false_string, "false", 5),
+ "Bool_To_String [false]");
+
+ DECREF(false_string);
+ DECREF(true_string);
+}
+
+static void
+test_accessors(TestBatchRunner *runner) {
+ TEST_INT_EQ(runner, Bool_Get_Value(CFISH_TRUE), true,
+ "Bool_Get_Value [true]");
+ TEST_INT_EQ(runner, Bool_Get_Value(CFISH_FALSE), false,
+ "Bool_Get_Value [false]");
+}
+
+static void
+test_Equals_and_Compare_To(TestBatchRunner *runner) {
+ TEST_TRUE(runner, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_TRUE),
+ "CFISH_TRUE Equals itself");
+ TEST_TRUE(runner, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_FALSE),
+ "CFISH_FALSE Equals itself");
+ TEST_FALSE(runner, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_TRUE),
+ "CFISH_FALSE not Equals CFISH_TRUE ");
+ TEST_FALSE(runner, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_FALSE),
+ "CFISH_TRUE not Equals CFISH_FALSE ");
+ TEST_FALSE(runner, Bool_Equals(CFISH_TRUE, (Obj*)STRING),
+ "CFISH_TRUE not Equals random other object ");
+}
+
+static void
+test_Clone(TestBatchRunner *runner) {
+ TEST_TRUE(runner, Bool_Equals(CFISH_TRUE, (Obj*)Bool_Clone(CFISH_TRUE)),
+ "Boolean Clone");
+}
+
+void
+TestBoolean_Run_IMP(TestBoolean *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 12);
+
+ // Destroying the singletons should have no effect.
+ Bool_Destroy(CFISH_TRUE);
+ Bool_Destroy(CFISH_FALSE);
+
+ test_singleton(runner);
+ test_To_String(runner);
+ test_accessors(runner);
+ test_Equals_and_Compare_To(runner);
+ test_Clone(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestBoolean.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestBoolean.cfh b/runtime/test/Clownfish/Test/TestBoolean.cfh
new file mode 100644
index 0000000..43702db
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestBoolean.cfh
@@ -0,0 +1,29 @@
+/* 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::TestBoolean
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestBoolean*
+ new();
+
+ void
+ Run(TestBoolean *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestByteBuf.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestByteBuf.c b/runtime/test/Clownfish/Test/TestByteBuf.c
new file mode 100644
index 0000000..7f8fc50
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestByteBuf.c
@@ -0,0 +1,218 @@
+/* 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/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Blob.h"
+#include "Clownfish/Class.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/String.h"
+#include "Clownfish/Util/Memory.h"
+
+#include <string.h>
+
+TestByteBuf*
+TestBB_new() {
+ return (TestByteBuf*)Class_Make_Obj(TESTBYTEBUF);
+}
+
+static void
+test_new_steal_bytes(TestBatchRunner *runner) {
+ char *buf = (char*)MALLOCATE(10);
+ memset(buf, 'x', 10);
+ ByteBuf *bb = BB_new_steal_bytes(buf, 5, 10);
+ TEST_TRUE(runner, BB_Get_Buf(bb) == buf, "new_steal_bytes steals buffer");
+ TEST_TRUE(runner, BB_Equals_Bytes(bb, "xxxxx", 5),
+ "new_steal_bytes sets correct size");
+ BB_Set_Size(bb, 10);
+ TEST_TRUE(runner, BB_Equals_Bytes(bb, "xxxxxxxxxx", 10),
+ "new_steal_bytes sets correct capacity");
+ DECREF(bb);
+}
+
+static void
+test_Equals(TestBatchRunner *runner) {
+ ByteBuf *bb = BB_new_bytes("foo", 4); // Include terminating NULL.
+
+ TEST_TRUE(runner, BB_Equals(bb, (Obj*)bb), "Equals self");
+ TEST_FALSE(runner, BB_Equals(bb, (Obj*)BYTEBUF),
+ "Equals spoiled by different type");
+
+ {
+ ByteBuf *other = BB_new_bytes("foo", 4);
+ TEST_TRUE(runner, BB_Equals(bb, (Obj*)other), "Equals");
+ DECREF(other);
+ }
+
+ TEST_TRUE(runner, BB_Equals_Bytes(bb, "foo", 4), "Equals_Bytes");
+ TEST_FALSE(runner, BB_Equals_Bytes(bb, "foo", 3),
+ "Equals_Bytes spoiled by different size");
+ TEST_FALSE(runner, BB_Equals_Bytes(bb, "bar", 4),
+ "Equals_Bytes spoiled by different content");
+
+ {
+ ByteBuf *other = BB_new_bytes("foo", 3);
+ TEST_FALSE(runner, BB_Equals(bb, (Obj*)other),
+ "Different size spoils Equals");
+ DECREF(other);
+ }
+
+ {
+ ByteBuf *other = BB_new_bytes("bar", 4);
+ TEST_UINT_EQ(runner, BB_Get_Size(bb), BB_Get_Size(other),
+ "same length");
+ TEST_FALSE(runner, BB_Equals(bb, (Obj*)other),
+ "Different content spoils Equals");
+ DECREF(other);
+ }
+
+ DECREF(bb);
+}
+
+static void
+test_Grow(TestBatchRunner *runner) {
+ ByteBuf *bb = BB_new(1);
+ TEST_UINT_EQ(runner, BB_Get_Capacity(bb), 8,
+ "Allocate in 8-byte increments");
+ BB_Grow(bb, 9);
+ TEST_UINT_EQ(runner, BB_Get_Capacity(bb), 16,
+ "Grow in 8-byte increments");
+ BB_Grow(bb, 16);
+ TEST_UINT_EQ(runner, BB_Get_Capacity(bb), 16,
+ "Grow to same capacity has no effect");
+ DECREF(bb);
+}
+
+static void
+test_Clone(TestBatchRunner *runner) {
+ ByteBuf *bb = BB_new_bytes("foo", 3);
+ ByteBuf *twin = BB_Clone(bb);
+ TEST_TRUE(runner, BB_Equals(bb, (Obj*)twin), "Clone");
+ DECREF(bb);
+ DECREF(twin);
+}
+
+static void
+test_Compare_To(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(runner, BB_Compare_To(a, (Obj*)b), 0,
+ "Compare_To returns 0 for equal ByteBufs");
+
+ BB_Set_Size(a, 3);
+ TEST_TRUE(runner, BB_Compare_To(a, (Obj*)b) < 0,
+ "shorter ByteBuf sorts first");
+ TEST_TRUE(runner, BB_Compare_To(b, (Obj*)a) > 0,
+ "longer ByteBuf sorts last");
+
+ BB_Set_Size(a, 5);
+ BB_Set_Size(b, 5);
+ TEST_TRUE(runner, BB_Compare_To(a, (Obj*)b) < 0,
+ "NULL doesn't interfere with Compare_To");
+
+ DECREF(a);
+ DECREF(b);
+}
+
+static void
+test_Cat(TestBatchRunner *runner) {
+ ByteBuf *bb = BB_new_bytes("foo", 3);
+
+ {
+ Blob *blob = Blob_new("bar", 3);
+ BB_Cat(bb, blob);
+ TEST_TRUE(runner, BB_Equals_Bytes(bb, "foobar", 6), "Cat");
+ DECREF(blob);
+ }
+
+ BB_Cat_Bytes(bb, "baz", 3);
+ TEST_TRUE(runner, BB_Equals_Bytes(bb, "foobarbaz", 9), "Cat_Bytes");
+
+ DECREF(bb);
+}
+
+static void
+test_Utf8_To_String(TestBatchRunner *runner) {
+ ByteBuf *bb = BB_new_bytes("foo", 3);
+
+ {
+ String *string = BB_Utf8_To_String(bb);
+ TEST_TRUE(runner, Str_Equals_Utf8(string, "foo", 3), "Utf8_To_String");
+ DECREF(string);
+ }
+
+ {
+ String *string = BB_Trusted_Utf8_To_String(bb);
+ TEST_TRUE(runner, Str_Equals_Utf8(string, "foo", 3),
+ "Trusted_Utf8_To_String");
+ DECREF(string);
+ }
+
+ DECREF(bb);
+}
+
+static void
+S_set_wrong_size(void *context) {
+ ByteBuf *bb = (ByteBuf*)context;
+ BB_Set_Size(bb, BB_Get_Capacity(bb) + 1);
+}
+
+static void
+test_Set_Size(TestBatchRunner *runner) {
+ ByteBuf *bb = BB_new(10);
+ Err *error = Err_trap(S_set_wrong_size, bb);
+ TEST_TRUE(runner, error != NULL, "Setting size beyond capacity throws");
+ DECREF(error);
+ DECREF(bb);
+}
+
+static void
+test_Yield_Blob(TestBatchRunner *runner) {
+ ByteBuf *bb = BB_new_bytes("alpha", 5);
+ Blob *blob = BB_Yield_Blob(bb);
+ TEST_TRUE(runner, Blob_Equals_Bytes(blob, "alpha", 5), "Yield_Blob");
+ TEST_UINT_EQ(runner, BB_Get_Size(bb), 0, "Yield_Blob clears buf");
+ DECREF(blob);
+ DECREF(bb);
+}
+
+void
+TestBB_Run_IMP(TestByteBuf *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 27);
+ test_new_steal_bytes(runner);
+ test_Equals(runner);
+ test_Grow(runner);
+ test_Clone(runner);
+ test_Compare_To(runner);
+ test_Cat(runner);
+ test_Utf8_To_String(runner);
+ test_Set_Size(runner);
+ test_Yield_Blob(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestByteBuf.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestByteBuf.cfh b/runtime/test/Clownfish/Test/TestByteBuf.cfh
new file mode 100644
index 0000000..d27e715
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestByteBuf.cfh
@@ -0,0 +1,29 @@
+/* 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 nickname TestBB
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestByteBuf*
+ new();
+
+ void
+ Run(TestByteBuf *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestCharBuf.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestCharBuf.c b/runtime/test/Clownfish/Test/TestCharBuf.c
new file mode 100644
index 0000000..4329987
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestCharBuf.c
@@ -0,0 +1,394 @@
+/* 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 CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+#define C_CFISH_CHARBUF
+
+#include "charmony.h"
+
+#include "Clownfish/Test/TestCharBuf.h"
+
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Num.h"
+#include "Clownfish/String.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Class.h"
+
+static char smiley[] = { (char)0xE2, (char)0x98, (char)0xBA, 0 };
+static uint32_t smiley_len = 3;
+
+TestCharBuf*
+TestCB_new() {
+ return (TestCharBuf*)Class_Make_Obj(TESTCHARBUF);
+}
+
+static CharBuf*
+S_get_cb(const char *string) {
+ CharBuf *cb = CB_new(0);
+ CB_Cat_Utf8(cb, string, strlen(string));
+ return cb;
+}
+
+static String*
+S_get_str(const char *string) {
+ return Str_new_from_utf8(string, strlen(string));
+}
+
+static bool
+S_cb_equals(CharBuf *cb, String *other) {
+ String *string = CB_To_String(cb);
+ bool retval = Str_Equals(string, (Obj*)other);
+ DECREF(string);
+ return retval;
+}
+
+static void
+S_cat_invalid_utf8(void *context) {
+ CharBuf *cb = (CharBuf*)context;
+ CB_Cat_Utf8(cb, "\xF0" "a", 2);
+}
+
+static void
+test_Cat(TestBatchRunner *runner) {
+ String *wanted = Str_newf("a%s", smiley);
+ CharBuf *got = S_get_cb("");
+
+ CB_Cat(got, wanted);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat");
+ DECREF(got);
+
+ got = S_get_cb("a");
+ CB_Cat_Char(got, 0x263A);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat_Char");
+ DECREF(got);
+
+ got = S_get_cb("a");
+ CB_Cat_Utf8(got, smiley, smiley_len);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat_Utf8");
+ DECREF(got);
+
+ got = S_get_cb("a");
+ Err *error = Err_trap(S_cat_invalid_utf8, got);
+ TEST_TRUE(runner, error != NULL, "Cat_Utf8 throws with invalid UTF-8");
+ DECREF(error);
+ DECREF(got);
+
+ got = S_get_cb("a");
+ CB_Cat_Trusted_Utf8(got, smiley, smiley_len);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat_Trusted_Utf8");
+ DECREF(got);
+
+ DECREF(wanted);
+}
+
+static void
+test_Clone(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo");
+ CharBuf *wanted_cb = S_get_cb("foo");
+ CharBuf *got = CB_Clone(wanted_cb);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "Clone");
+ DECREF(got);
+ DECREF(wanted);
+ DECREF(wanted_cb);
+}
+
+static void
+test_vcatf_percent(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo % bar");
+ CharBuf *got = S_get_cb("foo");
+ CB_catf(got, " %% bar");
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%%%");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_s(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo bar bizzle baz");
+ CharBuf *got = S_get_cb("foo ");
+ CB_catf(got, "bar %s baz", "bizzle");
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%s");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+S_catf_s_invalid_utf8(void *context) {
+ CharBuf *buf = (CharBuf*)context;
+ CB_catf(buf, "bar %s baz", "\x82" "abcd");
+}
+
+static void
+test_vcatf_s_invalid_utf8(TestBatchRunner *runner) {
+ CharBuf *buf = S_get_cb("foo ");
+ Err *error = Err_trap(S_catf_s_invalid_utf8, buf);
+ TEST_TRUE(runner, error != NULL, "%%s with invalid UTF-8");
+ DECREF(error);
+ DECREF(buf);
+}
+
+static void
+test_vcatf_null_string(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo bar [NULL] baz");
+ CharBuf *got = S_get_cb("foo ");
+ CB_catf(got, "bar %s baz", NULL);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%s NULL");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_str(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo bar ZEKE baz");
+ String *catworthy = S_get_str("ZEKE");
+ CharBuf *got = S_get_cb("foo ");
+ CB_catf(got, "bar %o baz", catworthy);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%o CharBuf");
+ DECREF(catworthy);
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_obj(TestBatchRunner *runner) {
+ String *wanted = S_get_str("ooga 20 booga");
+ Integer *i64 = Int_new(20);
+ CharBuf *got = S_get_cb("ooga");
+ CB_catf(got, " %o booga", i64);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%o Obj");
+ DECREF(i64);
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_null_obj(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo bar [NULL] baz");
+ CharBuf *got = S_get_cb("foo ");
+ CB_catf(got, "bar %o baz", NULL);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%o NULL");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_i8(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo bar -3 baz");
+ int8_t num = -3;
+ CharBuf *got = S_get_cb("foo ");
+ CB_catf(got, "bar %i8 baz", num);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%i8");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_i32(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo bar -100000 baz");
+ int32_t num = -100000;
+ CharBuf *got = S_get_cb("foo ");
+ CB_catf(got, "bar %i32 baz", num);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%i32");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_i64(TestBatchRunner *runner) {
+ String *wanted = S_get_str("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(runner, S_cb_equals(got, wanted), "%%i64");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_u8(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo bar 3 baz");
+ uint8_t num = 3;
+ CharBuf *got = S_get_cb("foo ");
+ CB_catf(got, "bar %u8 baz", num);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%u8");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_u32(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo bar 100000 baz");
+ uint32_t num = 100000;
+ CharBuf *got = S_get_cb("foo ");
+ CB_catf(got, "bar %u32 baz", num);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%u32");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_u64(TestBatchRunner *runner) {
+ String *wanted = S_get_str("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(runner, S_cb_equals(got, wanted), "%%u64");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_f64(TestBatchRunner *runner) {
+ String *wanted;
+ char buf[64];
+ float num = 1.3f;
+ CharBuf *got = S_get_cb("foo ");
+ sprintf(buf, "foo bar %g baz", num);
+ wanted = Str_new_from_trusted_utf8(buf, strlen(buf));
+ CB_catf(got, "bar %f64 baz", num);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%f64");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_vcatf_x32(TestBatchRunner *runner) {
+ String *wanted;
+ char buf[64];
+ unsigned long num = INT32_MAX;
+ CharBuf *got = S_get_cb("foo ");
+#if (CHY_SIZEOF_LONG == 4)
+ sprintf(buf, "foo bar %.8lx baz", num);
+#elif (CHY_SIZEOF_INT == 4)
+ sprintf(buf, "foo bar %.8x baz", (unsigned)num);
+#endif
+ wanted = Str_new_from_trusted_utf8(buf, strlen(buf));
+ CB_catf(got, "bar %x32 baz", (uint32_t)num);
+ TEST_TRUE(runner, S_cb_equals(got, wanted), "%%x32");
+ DECREF(wanted);
+ DECREF(got);
+}
+
+typedef struct {
+ CharBuf *charbuf;
+ const char *pattern;
+} CatfContext;
+
+static void
+S_catf_invalid_pattern(void *vcontext) {
+ CatfContext *context = (CatfContext*)vcontext;
+ CB_catf(context->charbuf, context->pattern, 0);
+}
+
+static void
+test_vcatf_invalid(TestBatchRunner *runner) {
+ CatfContext context;
+ context.charbuf = S_get_cb("foo ");
+
+ static const char *const patterns[] = {
+ "bar %z baz",
+ "bar %i baz",
+ "bar %i1 baz",
+ "bar %i33 baz",
+ "bar %i65 baz",
+ "bar %u baz",
+ "bar %u9 baz",
+ "bar %u33 baz",
+ "bar %u65 baz",
+ "bar %x baz",
+ "bar %x9 baz",
+ "bar %x33 baz",
+ "bar %f baz",
+ "bar %f9 baz",
+ "bar %f65 baz",
+ "bar \xC2 baz"
+ };
+ static const size_t num_patterns = sizeof(patterns) / sizeof(patterns[0]);
+
+ for (size_t i = 0; i < num_patterns; i++) {
+ context.pattern = patterns[i];
+ Err *error = Err_trap(S_catf_invalid_pattern, &context);
+ TEST_TRUE(runner, error != NULL,
+ "catf throws with invalid pattern '%s'", patterns[i]);
+ DECREF(error);
+ }
+
+ DECREF(context.charbuf);
+}
+
+static void
+test_Clear(TestBatchRunner *runner) {
+ CharBuf *cb = S_get_cb("foo");
+ CB_Clear(cb);
+ CB_Cat_Utf8(cb, "bar", 3);
+ String *string = CB_Yield_String(cb);
+ TEST_TRUE(runner, Str_Equals_Utf8(string, "bar", 3), "Clear");
+ DECREF(string);
+ DECREF(cb);
+}
+
+static void
+test_Grow(TestBatchRunner *runner) {
+ CharBuf *cb = S_get_cb("omega");
+ CB_Grow(cb, 100);
+ size_t cap = cb->cap;
+ TEST_TRUE(runner, cap >= 100, "Grow");
+ CB_Grow(cb, 100);
+ TEST_UINT_EQ(runner, cb->cap, cap, "Grow to same size has no effect");
+ DECREF(cb);
+}
+
+static void
+test_Get_Size(TestBatchRunner *runner) {
+ CharBuf *got = S_get_cb("a");
+ CB_Cat_Utf8(got, smiley, smiley_len);
+ TEST_UINT_EQ(runner, CB_Get_Size(got), smiley_len + 1, "Get_Size");
+ DECREF(got);
+}
+
+void
+TestCB_Run_IMP(TestCharBuf *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 41);
+ test_vcatf_percent(runner);
+ test_vcatf_s(runner);
+ test_vcatf_s_invalid_utf8(runner);
+ test_vcatf_null_string(runner);
+ test_vcatf_str(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_vcatf_invalid(runner);
+ test_Cat(runner);
+ test_Clone(runner);
+ test_Clear(runner);
+ test_Grow(runner);
+ test_Get_Size(runner);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestCharBuf.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestCharBuf.cfh b/runtime/test/Clownfish/Test/TestCharBuf.cfh
new file mode 100644
index 0000000..d568c14
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestCharBuf.cfh
@@ -0,0 +1,29 @@
+/* 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 nickname TestCB
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestCharBuf*
+ new();
+
+ void
+ Run(TestCharBuf *self, TestBatchRunner *runner);
+}
+
+
[08/14] lucy-clownfish git commit: Move tests to separate directory
Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestHost.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestHost.c b/runtime/core/Clownfish/Test/TestHost.c
deleted file mode 100644
index 6da0efa..0000000
--- a/runtime/core/Clownfish/Test/TestHost.c
+++ /dev/null
@@ -1,125 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestHost.h"
-#include "Clownfish/Class.h"
-#include "Clownfish/String.h"
-
-TestHost*
-TestHost_new() {
- return (TestHost*)Class_Make_Obj(TESTHOST);
-}
-
-Obj*
-TestHost_Test_Obj_Pos_Arg_IMP(TestHost *self, Obj *arg) {
- UNUSED_VAR(self);
- return arg;
-}
-
-Obj*
-TestHost_Test_Obj_Pos_Arg_Def_IMP(TestHost *self, Obj *arg) {
- UNUSED_VAR(self);
- return arg;
-}
-
-Obj*
-TestHost_Test_Obj_Label_Arg_IMP(TestHost *self, Obj *arg, bool unused) {
- UNUSED_VAR(self);
- UNUSED_VAR(unused);
- return arg;
-}
-
-Obj*
-TestHost_Test_Obj_Label_Arg_Def_IMP(TestHost *self, Obj *arg, bool unused) {
- UNUSED_VAR(self);
- UNUSED_VAR(unused);
- return arg;
-}
-
-int32_t
-TestHost_Test_Int32_Pos_Arg_IMP(TestHost *self, int32_t arg) {
- UNUSED_VAR(self);
- return arg;
-}
-
-int32_t
-TestHost_Test_Int32_Pos_Arg_Def_IMP(TestHost *self, int32_t arg) {
- UNUSED_VAR(self);
- return arg;
-}
-
-int32_t
-TestHost_Test_Int32_Label_Arg_IMP(TestHost *self, int32_t arg, bool unused) {
- UNUSED_VAR(self);
- UNUSED_VAR(unused);
- return arg;
-}
-
-int32_t
-TestHost_Test_Int32_Label_Arg_Def_IMP(TestHost *self, int32_t arg,
- bool unused) {
- UNUSED_VAR(self);
- UNUSED_VAR(unused);
- return arg;
-}
-
-bool
-TestHost_Test_Bool_Pos_Arg_IMP(TestHost *self, bool arg) {
- UNUSED_VAR(self);
- return arg;
-}
-
-bool
-TestHost_Test_Bool_Pos_Arg_Def_IMP(TestHost *self, bool arg) {
- UNUSED_VAR(self);
- return arg;
-}
-
-bool
-TestHost_Test_Bool_Label_Arg_IMP(TestHost *self, bool arg, bool unused) {
- UNUSED_VAR(self);
- UNUSED_VAR(unused);
- return arg;
-}
-
-bool
-TestHost_Test_Bool_Label_Arg_Def_IMP(TestHost *self, bool arg, bool unused) {
- UNUSED_VAR(self);
- UNUSED_VAR(unused);
- return arg;
-}
-
-void
-TestHost_Invoke_Invalid_Callback_From_C_IMP(TestHost *self) {
- TestHost_Invalid_Callback(self);
-}
-
-String*
-TestHost_Aliased_IMP(TestHost *self) {
- UNUSED_VAR(self);
- return Str_newf("C");
-}
-
-String*
-TestHost_Invoke_Aliased_From_C_IMP(TestHost *self) {
- UNUSED_VAR(self);
- return TestHost_Aliased(self);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestHost.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestHost.cfh b/runtime/core/Clownfish/Test/TestHost.cfh
deleted file mode 100644
index 92bc272..0000000
--- a/runtime/core/Clownfish/Test/TestHost.cfh
+++ /dev/null
@@ -1,81 +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 TestClownfish;
-
-/** Clownfish test suite.
- */
-class Clownfish::Test::TestHost {
- inert incremented TestHost*
- new();
-
- Obj*
- Test_Obj_Pos_Arg(TestHost *self, Obj *arg);
-
- Obj*
- Test_Obj_Pos_Arg_Def(TestHost *self, nullable Obj *arg = NULL);
-
- Obj*
- Test_Obj_Label_Arg(TestHost *self, Obj *arg, bool unused = false);
-
- Obj*
- Test_Obj_Label_Arg_Def(TestHost *self, nullable Obj *arg = NULL,
- bool unused = false);
-
- int32_t
- Test_Int32_Pos_Arg(TestHost *self, int32_t arg);
-
- int32_t
- Test_Int32_Pos_Arg_Def(TestHost *self, int32_t arg = 101);
-
- int32_t
- Test_Int32_Label_Arg(TestHost *self, int32_t arg, bool unused = false);
-
- int32_t
- Test_Int32_Label_Arg_Def(TestHost *self, int32_t arg = 101,
- bool unused = false);
-
- bool
- Test_Bool_Pos_Arg(TestHost *self, bool arg);
-
- bool
- Test_Bool_Pos_Arg_Def(TestHost *self, bool arg = true);
-
- bool
- Test_Bool_Label_Arg(TestHost *self, bool arg, bool unused = false);
-
- bool
- Test_Bool_Label_Arg_Def(TestHost *self, bool arg = true,
- bool unused = false);
-
- /** A method that can't be overridden from the host language.
- */
- abstract void*
- Invalid_Callback(TestHost *self);
-
- void
- Invoke_Invalid_Callback_From_C(TestHost *self);
-
- /** A method with a custom host language alias.
- */
- incremented String*
- Aliased(TestHost *self);
-
- incremented String*
- Invoke_Aliased_From_C(TestHost* self);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestLockFreeRegistry.c b/runtime/core/Clownfish/Test/TestLockFreeRegistry.c
deleted file mode 100644
index b70ff1f..0000000
--- a/runtime/core/Clownfish/Test/TestLockFreeRegistry.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.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#define CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestLockFreeRegistry.h"
-
-#include "Clownfish/Class.h"
-#include "Clownfish/LockFreeRegistry.h"
-#include "Clownfish/String.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Util/Memory.h"
-
-#define NUM_THREADS 5
-
-typedef struct ThreadArgs {
- LockFreeRegistry *registry;
- uint32_t *nums;
- uint32_t num_objs;
- uint64_t target_time;
- uint32_t succeeded;
-} ThreadArgs;
-
-TestLockFreeRegistry*
-TestLFReg_new() {
- return (TestLockFreeRegistry*)Class_Make_Obj(TESTLOCKFREEREGISTRY);
-}
-
-static void
-test_all(TestBatchRunner *runner) {
- LockFreeRegistry *registry = LFReg_new(1);
- String *foo = Str_newf("foo");
- String *bar = Str_newf("bar");
- String *baz = Str_newf("baz");
- String *foo_dupe = Str_newf("foo");
-
- TEST_TRUE(runner, LFReg_register(registry, foo, (Obj*)foo),
- "Register() returns true on success");
- TEST_FALSE(runner,
- LFReg_register(registry, foo_dupe, (Obj*)foo_dupe),
- "Can't Register() keys that test equal");
-
- TEST_TRUE(runner, LFReg_register(registry, bar, (Obj*)bar),
- "Register() key with the same Hash_Sum but that isn't Equal");
-
- TEST_TRUE(runner, LFReg_fetch(registry, foo_dupe) == (Obj*)foo,
- "Fetch()");
- TEST_TRUE(runner, LFReg_fetch(registry, bar) == (Obj*)bar,
- "Fetch() again");
- TEST_TRUE(runner, LFReg_fetch(registry, baz) == NULL,
- "Fetch() non-existent key returns NULL");
-
- DECREF(foo_dupe);
- DECREF(baz);
- DECREF(bar);
- DECREF(foo);
- LFReg_destroy(registry);
-}
-
-static void
-S_register_many(void *varg) {
- ThreadArgs *args = (ThreadArgs*)varg;
-
- // Encourage contention, so that all threads try to register at the same
- // time.
-
- // Sleep until target_time.
- uint64_t time = TestUtils_time();
- if (args->target_time > time) {
- TestUtils_usleep(args->target_time - time);
- }
-
- TestUtils_thread_yield();
-
- uint32_t succeeded = 0;
- for (uint32_t i = 0; i < args->num_objs; i++) {
- String *obj = Str_newf("%u32", args->nums[i]);
- if (LFReg_register(args->registry, obj, (Obj*)obj)) {
- succeeded++;
- }
- DECREF(obj);
- }
-
- args->succeeded = succeeded;
-}
-
-static void
-test_threads(TestBatchRunner *runner) {
- if (!TestUtils_has_threads) {
- SKIP(runner, 1, "No thread support");
- return;
- }
-
- LockFreeRegistry *registry = LFReg_new(32);
- ThreadArgs thread_args[NUM_THREADS];
- uint32_t num_objs = 10000;
-
- for (uint32_t i = 0; i < NUM_THREADS; i++) {
- uint32_t *nums = (uint32_t*)MALLOCATE(num_objs * sizeof(uint32_t));
-
- for (uint32_t j = 0; j < num_objs; j++) {
- nums[j] = j;
- }
-
- // Fisher-Yates shuffle.
- for (uint32_t j = num_objs - 1; j > 0; j--) {
- uint32_t r = (uint32_t)TestUtils_random_u64() % (j + 1);
- uint32_t tmp = nums[j];
- nums[j] = nums[r];
- nums[r] = tmp;
- }
-
- thread_args[i].registry = registry;
- thread_args[i].nums = nums;
- thread_args[i].num_objs = num_objs;
- }
-
- Thread *threads[NUM_THREADS];
- uint64_t target_time = TestUtils_time() + 200 * 1000;
-
- for (uint32_t i = 0; i < NUM_THREADS; i++) {
- thread_args[i].target_time = target_time;
- threads[i]
- = TestUtils_thread_create(S_register_many, &thread_args[i], NULL);
- }
-
- uint32_t total_succeeded = 0;
-
- for (uint32_t i = 0; i < NUM_THREADS; i++) {
- TestUtils_thread_join(threads[i]);
- total_succeeded += thread_args[i].succeeded;
- FREEMEM(thread_args[i].nums);
- }
-
- TEST_INT_EQ(runner, total_succeeded, num_objs,
- "registered exactly the right number of entries across all"
- " threads");
-
- LFReg_destroy(registry);
-}
-
-void
-TestLFReg_Run_IMP(TestLockFreeRegistry *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 7);
- test_all(runner);
- test_threads(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestLockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestLockFreeRegistry.cfh b/runtime/core/Clownfish/Test/TestLockFreeRegistry.cfh
deleted file mode 100644
index 784f745..0000000
--- a/runtime/core/Clownfish/Test/TestLockFreeRegistry.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::TestLockFreeRegistry nickname TestLFReg
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestLockFreeRegistry*
- new();
-
- void
- Run(TestLockFreeRegistry *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestMethod.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestMethod.c b/runtime/core/Clownfish/Test/TestMethod.c
deleted file mode 100644
index 7c39759..0000000
--- a/runtime/core/Clownfish/Test/TestMethod.c
+++ /dev/null
@@ -1,91 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestMethod.h"
-
-#include "Clownfish/Err.h"
-#include "Clownfish/Method.h"
-#include "Clownfish/String.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-
-TestMethod*
-TestMethod_new() {
- return (TestMethod*)Class_Make_Obj(TESTMETHOD);
-}
-
-static void
-S_set_host_alias(void *context) {
- Method *method = (Method*)context;
- Method_Set_Host_Alias(method, SSTR_WRAP_C("foo"));
-}
-
-static void
-test_accessors(TestBatchRunner *runner) {
- String *name = SSTR_WRAP_C("Frobnicate_Widget");
- Method *method = Method_new(name, NULL, 0);
-
- TEST_TRUE(runner, Str_Equals(Method_Get_Name(method), (Obj*)name),
- "Get_Name");
-
- String *alias = SSTR_WRAP_C("host_frob");
- Method_Set_Host_Alias(method, alias);
- TEST_TRUE(runner, Str_Equals(Method_Get_Host_Alias(method), (Obj*)alias),
- "Set_Host_Alias");
- Err *error = Err_trap(S_set_host_alias, method);
- TEST_TRUE(runner, error != NULL,
- "Set_Host_Alias can't be called more than once");
- DECREF(error);
-
- TEST_FALSE(runner, Method_Is_Excluded_From_Host(method),
- "Is_Excluded_From_Host");
-
- Method_Destroy(method);
-}
-
-static void
-test_lower_snake_alias(TestBatchRunner *runner) {
- String *name = SSTR_WRAP_C("Frobnicate_Widget");
- Method *method = Method_new(name, NULL, 0);
-
- {
- String *alias = Method_lower_snake_alias(method);
- TEST_TRUE(runner, Str_Equals_Utf8(alias, "frobnicate_widget", 17),
- "lower_snake_alias without explicit alias");
- DECREF(alias);
- }
-
- {
- String *new_alias = SSTR_WRAP_C("host_frob");
- Method_Set_Host_Alias(method, new_alias);
- String *alias = Method_lower_snake_alias(method);
- TEST_TRUE(runner, Str_Equals(alias, (Obj*)new_alias),
- "lower_snake_alias with explicit alias");
- DECREF(alias);
- }
-
- Method_Destroy(method);
-}
-
-void
-TestMethod_Run_IMP(TestMethod *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
- test_accessors(runner);
- test_lower_snake_alias(runner);
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestMethod.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestMethod.cfh b/runtime/core/Clownfish/Test/TestMethod.cfh
deleted file mode 100644
index 76b9558..0000000
--- a/runtime/core/Clownfish/Test/TestMethod.cfh
+++ /dev/null
@@ -1,28 +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 TestClownfish;
-
-class Clownfish::Test::TestMethod
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestMethod*
- new();
-
- void
- Run(TestMethod *self, TestBatchRunner *runner);
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestNum.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestNum.c b/runtime/core/Clownfish/Test/TestNum.c
deleted file mode 100644
index dfa6769..0000000
--- a/runtime/core/Clownfish/Test/TestNum.c
+++ /dev/null
@@ -1,278 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include <math.h>
-
-#include "charmony.h"
-
-#include "Clownfish/Test/TestNum.h"
-
-#include "Clownfish/Err.h"
-#include "Clownfish/String.h"
-#include "Clownfish/Num.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Class.h"
-
-TestNum*
-TestNum_new() {
- return (TestNum*)Class_Make_Obj(TESTNUM);
-}
-
-static void
-test_To_String(TestBatchRunner *runner) {
- Float *f64 = Float_new(1.33);
- Integer *i64 = Int_new(INT64_MAX);
- String *f64_string = Float_To_String(f64);
- String *i64_string = Int_To_String(i64);
-
- TEST_TRUE(runner, Str_Starts_With_Utf8(f64_string, "1.3", 3),
- "Float_To_String");
- TEST_TRUE(runner, Str_Equals_Utf8(i64_string, "9223372036854775807", 19),
- "Int_To_String");
-
- DECREF(i64_string);
- DECREF(f64_string);
- DECREF(i64);
- DECREF(f64);
-}
-
-static void
-S_float_to_i64(void *context) {
- Float *f = (Float*)context;
- Float_To_I64(f);
-}
-
-static void
-test_accessors(TestBatchRunner *runner) {
- Float *f64 = Float_new(1.33);
- Integer *i64 = Int_new(INT64_MIN);
- double wanted64 = 1.33;
- double got64;
-
- got64 = Float_Get_Value(f64);
- TEST_TRUE(runner, *(int64_t*)&got64 == *(int64_t*)&wanted64,
- "F64 Get_Value");
- TEST_TRUE(runner, Float_To_I64(f64) == 1, "Float_To_I64");
-
- {
- Float *huge = Float_new(1e40);
- Err *error = Err_trap(S_float_to_i64, huge);
- TEST_TRUE(runner, error != NULL,
- "Float_To_I64 throws when out of range (+)");
- DECREF(error);
- DECREF(huge);
- }
-
- {
- Float *huge = Float_new(-1e40);
- Err *error = Err_trap(S_float_to_i64, huge);
- TEST_TRUE(runner, error != NULL,
- "Float_To_I64 throws when out of range (-)");
- DECREF(error);
- DECREF(huge);
- }
-
- TEST_TRUE(runner, Int_Get_Value(i64) == INT64_MIN, "I64 Get_Value");
- TEST_TRUE(runner, Int_To_F64(i64) == -9223372036854775808.0, "Int_To_F64");
-
- DECREF(i64);
- DECREF(f64);
-}
-
-static void
-S_test_compare_float_int(TestBatchRunner *runner, double f64_val,
- int64_t i64_val, int32_t result) {
- Float *f64;
- Integer *i64;
-
- f64 = Float_new(f64_val);
- i64 = Int_new(i64_val);
- TEST_INT_EQ(runner, Float_Compare_To(f64, (Obj*)i64), result,
- "Float_Compare_To %f %" PRId64, f64_val, i64_val);
- TEST_INT_EQ(runner, Int_Compare_To(i64, (Obj*)f64), -result,
- "Int_Compare_To %" PRId64" %f", i64_val, f64_val);
- TEST_INT_EQ(runner, Float_Equals(f64, (Obj*)i64), result == 0,
- "Float_Equals %f %" PRId64, f64_val, i64_val);
- TEST_INT_EQ(runner, Int_Equals(i64, (Obj*)f64), result == 0,
- "Int_Equals %" PRId64 " %f", i64_val, f64_val);
- DECREF(f64);
- DECREF(i64);
-
- if (i64_val == INT64_MIN) { return; }
-
- f64 = Float_new(-f64_val);
- i64 = Int_new(-i64_val);
- TEST_INT_EQ(runner, Float_Compare_To(f64, (Obj*)i64), -result,
- "Float_Compare_To %f %" PRId64, -f64_val, -i64_val);
- TEST_INT_EQ(runner, Int_Compare_To(i64, (Obj*)f64), result,
- "Int_Compare_To %" PRId64" %f", -i64_val, -f64_val);
- TEST_INT_EQ(runner, Float_Equals(f64, (Obj*)i64), result == 0,
- "Float_Equals %f %" PRId64, -f64_val, -i64_val);
- TEST_INT_EQ(runner, Int_Equals(i64, (Obj*)f64), result == 0,
- "Int_Equals %" PRId64 " %f", -i64_val, -f64_val);
- DECREF(f64);
- DECREF(i64);
-}
-
-static void
-S_float_compare_to(void *context) {
- Float *f = (Float*)context;
- Float_Compare_To(f, (Obj*)OBJ);
-}
-
-static void
-S_int_compare_to(void *context) {
- Integer *i = (Integer*)context;
- Int_Compare_To(i, (Obj*)OBJ);
-}
-
-static void
-test_Equals_and_Compare_To(TestBatchRunner *runner) {
- {
- Float *f1 = Float_new(1.0);
- Float *f2 = Float_new(1.0);
- TEST_TRUE(runner, Float_Compare_To(f1, (Obj*)f2) == 0,
- "Float_Compare_To equal");
- TEST_TRUE(runner, Float_Equals(f1, (Obj*)f2),
- "Float_Equals equal");
- DECREF(f1);
- DECREF(f2);
- }
-
- {
- Float *f1 = Float_new(1.0);
- Float *f2 = Float_new(2.0);
- TEST_TRUE(runner, Float_Compare_To(f1, (Obj*)f2) < 0,
- "Float_Compare_To less than");
- TEST_FALSE(runner, Float_Equals(f1, (Obj*)f2),
- "Float_Equals less than");
- DECREF(f1);
- DECREF(f2);
- }
-
- {
- Float *f1 = Float_new(1.0);
- Float *f2 = Float_new(0.0);
- TEST_TRUE(runner, Float_Compare_To(f1, (Obj*)f2) > 0,
- "Float_Compare_To greater than");
- TEST_FALSE(runner, Float_Equals(f1, (Obj*)f2),
- "Float_Equals greater than");
- DECREF(f1);
- DECREF(f2);
- }
-
- {
- Float *f = Float_new(1.0);
- Err *error = Err_trap(S_float_compare_to, f);
- TEST_TRUE(runner, error != NULL,
- "Float_Compare_To with invalid type throws");
- TEST_FALSE(runner, Float_Equals(f, (Obj*)OBJ),
- "Float_Equals with different type");
- DECREF(error);
- DECREF(f);
- }
-
- {
- Integer *i1 = Int_new(INT64_C(0x6666666666666666));
- Integer *i2 = Int_new(INT64_C(0x6666666666666666));
- TEST_TRUE(runner, Int_Compare_To(i1, (Obj*)i2) == 0,
- "Int_Compare_To equal");
- TEST_TRUE(runner, Int_Equals(i1, (Obj*)i2),
- "Int_Equals equal");
- DECREF(i1);
- DECREF(i2);
- }
-
- {
- Integer *i1 = Int_new(INT64_C(0x6666666666666666));
- Integer *i2 = Int_new(INT64_C(0x6666666666666667));
- TEST_TRUE(runner, Int_Compare_To(i1, (Obj*)i2) < 0,
- "Int_Compare_To less than");
- TEST_FALSE(runner, Int_Equals(i1, (Obj*)i2),
- "Int_Equals less than");
- DECREF(i1);
- DECREF(i2);
- }
-
- {
- Integer *i1 = Int_new(INT64_C(0x6666666666666666));
- Integer *i2 = Int_new(INT64_C(0x6666666666666665));
- TEST_TRUE(runner, Int_Compare_To(i1, (Obj*)i2) > 0,
- "Int_Compare_To greater than");
- TEST_FALSE(runner, Int_Equals(i1, (Obj*)i2),
- "Int_Equals greater than");
- DECREF(i1);
- DECREF(i2);
- }
-
- {
- Integer *i = Int_new(0);
- Err *error = Err_trap(S_int_compare_to, i);
- TEST_TRUE(runner, error != NULL,
- "Int_Compare_To with invalid type throws");
- TEST_FALSE(runner, Int_Equals(i, (Obj*)OBJ),
- "Int_Equals with different type");
- DECREF(error);
- DECREF(i);
- }
-
- // NOTICE: When running these tests on x86/x64, it's best to compile
- // with -ffloat-store to avoid excess FPU precision which can hide
- // implementation bugs.
- S_test_compare_float_int(runner, (double)INT64_MAX * 2.0, INT64_MAX, 1);
- S_test_compare_float_int(runner, pow(2.0, 60.0), INT64_C(1) << 60, 0);
- S_test_compare_float_int(runner, pow(2.0, 60.0), (INT64_C(1) << 60) - 1,
- 1);
- S_test_compare_float_int(runner, pow(2.0, 60.0), (INT64_C(1) << 60) + 1,
- -1);
- S_test_compare_float_int(runner, pow(2.0, 63.0), INT64_MAX, 1);
- S_test_compare_float_int(runner, -pow(2.0, 63.0), INT64_MIN, 0);
- // -9223372036854777856.0 == nextafter(-pow(2, 63), -INFINITY)
- S_test_compare_float_int(runner, -9223372036854777856.0, INT64_MIN, -1);
- S_test_compare_float_int(runner, 1.0, 2, -1);
-}
-
-static void
-test_Clone(TestBatchRunner *runner) {
- Float *f64 = Float_new(1.33);
- Integer *i64 = Int_new(INT64_MAX);
- Float *f64_dupe = Float_Clone(f64);
- Integer *i64_dupe = Int_Clone(i64);
- TEST_TRUE(runner, Float_Equals(f64, (Obj*)f64_dupe),
- "Float Clone");
- TEST_TRUE(runner, Int_Equals(i64, (Obj*)i64_dupe),
- "Integer Clone");
- DECREF(i64_dupe);
- DECREF(f64_dupe);
- DECREF(i64);
- DECREF(f64);
-}
-
-void
-TestNum_Run_IMP(TestNum *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 82);
- test_To_String(runner);
- test_accessors(runner);
- test_Equals_and_Compare_To(runner);
- test_Clone(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestNum.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestNum.cfh b/runtime/core/Clownfish/Test/TestNum.cfh
deleted file mode 100644
index 6d1f663..0000000
--- a/runtime/core/Clownfish/Test/TestNum.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::TestNum
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestNum*
- new();
-
- void
- Run(TestNum *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestObj.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestObj.c b/runtime/core/Clownfish/Test/TestObj.c
deleted file mode 100644
index c4cdafe..0000000
--- a/runtime/core/Clownfish/Test/TestObj.c
+++ /dev/null
@@ -1,152 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "charmony.h"
-
-#include "Clownfish/Test/TestObj.h"
-
-#include "Clownfish/String.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/Class.h"
-
-TestObj*
-TestObj_new() {
- return (TestObj*)Class_Make_Obj(TESTOBJ);
-}
-
-static Obj*
-S_new_testobj() {
- String *class_name = SSTR_WRAP_C("TestObj");
- Obj *obj;
- Class *klass = Class_fetch_class(class_name);
- if (!klass) {
- klass = Class_singleton(class_name, OBJ);
- }
- obj = Class_Make_Obj(klass);
- return Obj_init(obj);
-}
-
-static void
-test_refcounts(TestBatchRunner *runner) {
- Obj *obj = S_new_testobj();
-
- TEST_INT_EQ(runner, CFISH_REFCOUNT_NN(obj), 1,
- "Correct starting refcount");
-
- obj = CFISH_INCREF_NN(obj);
- TEST_INT_EQ(runner, CFISH_REFCOUNT_NN(obj), 2, "INCREF_NN");
-
- CFISH_DECREF_NN(obj);
- TEST_INT_EQ(runner, CFISH_REFCOUNT_NN(obj), 1, "DECREF_NN");
-
- DECREF(obj);
-}
-
-static void
-test_To_String(TestBatchRunner *runner) {
- Obj *testobj = S_new_testobj();
- String *string = Obj_To_String(testobj);
- TEST_TRUE(runner, Str_Contains_Utf8(string, "TestObj", 7), "To_String");
- DECREF(string);
- DECREF(testobj);
-}
-
-static void
-test_Equals(TestBatchRunner *runner) {
- Obj *testobj = S_new_testobj();
- Obj *other = S_new_testobj();
-
- TEST_TRUE(runner, Obj_Equals(testobj, testobj),
- "Equals is true for the same object");
- TEST_FALSE(runner, Obj_Equals(testobj, other),
- "Distinct objects are not equal");
-
- DECREF(testobj);
- DECREF(other);
-}
-
-static void
-test_is_a(TestBatchRunner *runner) {
- String *string = Str_new_from_trusted_utf8("", 0);
- Class *str_class = Str_get_class(string);
- String *class_name = Str_get_class_name(string);
-
- TEST_TRUE(runner, Str_is_a(string, STRING), "String is_a String.");
- TEST_TRUE(runner, Str_is_a(string, OBJ), "String is_a Obj.");
- TEST_TRUE(runner, str_class == STRING, "get_class");
- TEST_TRUE(runner, Str_Equals(Class_Get_Name(STRING), (Obj*)class_name),
- "get_class_name");
- TEST_FALSE(runner, Obj_is_a(NULL, OBJ), "NULL is not an Obj");
-
- DECREF(string);
-}
-
-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_Compare_To(void *context) {
- Obj_Compare_To((Obj*)context, (Obj*)context);
-}
-
-static void
-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(runner, error != NULL
- && Err_is_a(error, ERR)
- && Str_Contains_Utf8(Err_Get_Mess(error), "bstract", 7),
- message);
- DECREF(error);
-}
-
-static void
-test_abstract_routines(TestBatchRunner *runner) {
- Obj *blank = Class_Make_Obj(OBJ);
- S_verify_abstract_error(runner, S_attempt_init, blank, "init");
-
- Obj *obj = S_new_testobj();
- S_verify_abstract_error(runner, S_attempt_Clone, obj, "Clone");
- S_verify_abstract_error(runner, S_attempt_Compare_To, obj, "Compare_To");
- DECREF(obj);
-}
-
-void
-TestObj_Run_IMP(TestObj *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 14);
- test_refcounts(runner);
- test_To_String(runner);
- test_Equals(runner);
- test_is_a(runner);
- test_abstract_routines(runner);
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestObj.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestObj.cfh b/runtime/core/Clownfish/Test/TestObj.cfh
deleted file mode 100644
index c5cc401..0000000
--- a/runtime/core/Clownfish/Test/TestObj.cfh
+++ /dev/null
@@ -1,28 +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 TestClownfish;
-
-class Clownfish::Test::TestObj
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestObj*
- new();
-
- void
- Run(TestObj *self, TestBatchRunner *runner);
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestPtrHash.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestPtrHash.c b/runtime/core/Clownfish/Test/TestPtrHash.c
deleted file mode 100644
index 3bf7003..0000000
--- a/runtime/core/Clownfish/Test/TestPtrHash.c
+++ /dev/null
@@ -1,108 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include <stdlib.h>
-#include <time.h>
-
-#include "Clownfish/Test/TestPtrHash.h"
-#include "Clownfish/Class.h"
-#include "Clownfish/PtrHash.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Util/Memory.h"
-
-TestPtrHash*
-TestPtrHash_new() {
- return (TestPtrHash*)Class_Make_Obj(TESTPTRHASH);
-}
-
-static void
-test_Store_and_Fetch(TestBatchRunner *runner) {
- PtrHash *hash = PtrHash_new(100);
- char dummy[100];
-
- for (int i = 0; i < 100; i++) {
- void *key = &dummy[i];
- PtrHash_Store(hash, key, key);
- }
-
- bool all_equal = true;
- for (int i = 0; i < 100; i++) {
- void *key = &dummy[i];
- void *value = PtrHash_Fetch(hash, key);
- if (value != key) {
- all_equal = false;
- break;
- }
- }
- TEST_TRUE(runner, all_equal, "basic Store and Fetch");
-
- TEST_TRUE(runner, PtrHash_Fetch(hash, &dummy[100]) == NULL,
- "Fetch against non-existent key returns NULL");
-
- PtrHash_Store(hash, &dummy[50], dummy);
- TEST_TRUE(runner, PtrHash_Fetch(hash, &dummy[50]) == dummy,
- "Store replaces existing value");
-
- PtrHash_Destroy(hash);
-}
-
-static void
-test_stress(TestBatchRunner *runner) {
- PtrHash *hash = PtrHash_new(0); // trigger multiple rebuilds.
- size_t num_elems = 200000;
- void **keys = (void**)MALLOCATE(num_elems * sizeof(void*));
-
- for (size_t i = 0; i < num_elems; i++) {
- size_t index = (size_t)(TestUtils_random_u64() % num_elems);
- void *key = &keys[index];
- PtrHash_Store(hash, key, key);
- keys[i] = key;
- }
-
- // Overwrite for good measure.
- for (size_t i = 0; i < num_elems; i++) {
- void *key = keys[i];
- PtrHash_Store(hash, key, key);
- }
-
- bool all_equal = true;
- for (size_t i = 0; i < num_elems; i++) {
- void *key = keys[i];
- void *got = PtrHash_Fetch(hash, key);
- if (got != key) {
- all_equal = false;
- break;
- }
- }
- TEST_TRUE(runner, all_equal, "stress test");
-
- FREEMEM(keys);
- PtrHash_Destroy(hash);
-}
-
-void
-TestPtrHash_Run_IMP(TestPtrHash *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
- srand((unsigned int)time(NULL));
- test_Store_and_Fetch(runner);
- test_stress(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestPtrHash.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestPtrHash.cfh b/runtime/core/Clownfish/Test/TestPtrHash.cfh
deleted file mode 100644
index 83589cb..0000000
--- a/runtime/core/Clownfish/Test/TestPtrHash.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::TestPtrHash
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestPtrHash*
- new();
-
- void
- Run(TestPtrHash *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestString.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestString.c b/runtime/core/Clownfish/Test/TestString.c
deleted file mode 100644
index d89b5fe..0000000
--- a/runtime/core/Clownfish/Test/TestString.c
+++ /dev/null
@@ -1,848 +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 <stdio.h>
-
-#define CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestString.h"
-
-#include "Clownfish/String.h"
-#include "Clownfish/Boolean.h"
-#include "Clownfish/ByteBuf.h"
-#include "Clownfish/CharBuf.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Util/Memory.h"
-#include "Clownfish/Class.h"
-
-#define SMILEY "\xE2\x98\xBA"
-static char smiley[] = { (char)0xE2, (char)0x98, (char)0xBA, 0 };
-static uint32_t smiley_len = 3;
-static int32_t smiley_cp = 0x263A;
-
-TestString*
-TestStr_new() {
- return (TestString*)Class_Make_Obj(TESTSTRING);
-}
-
-static String*
-S_get_str(const char *string) {
- return Str_new_from_utf8(string, strlen(string));
-}
-
-// Surround a smiley with lots of whitespace.
-static String*
-S_smiley_with_whitespace(size_t *num_spaces_ptr) {
- int32_t spaces[] = {
- ' ', '\t', '\r', '\n', 0x000B, 0x000C, 0x000D, 0x0085,
- 0x00A0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
- 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029, 0x202F,
- 0x205F, 0x3000
- };
- size_t num_spaces = sizeof(spaces) / sizeof(uint32_t);
-
- CharBuf *buf = CB_new(0);
- for (size_t i = 0; i < num_spaces; i++) { CB_Cat_Char(buf, spaces[i]); }
- CB_Cat_Char(buf, smiley_cp);
- for (size_t i = 0; i < num_spaces; i++) { CB_Cat_Char(buf, spaces[i]); }
-
- String *retval = CB_To_String(buf);
- if (num_spaces_ptr) { *num_spaces_ptr = num_spaces; }
-
- DECREF(buf);
- return retval;
-}
-
-static void
-test_new(TestBatchRunner *runner) {
- static char chars[] = "A string " SMILEY " with a smile.";
-
- {
- char *buffer = (char*)MALLOCATE(sizeof(chars));
- strcpy(buffer, chars);
- String *thief = Str_new_steal_utf8(buffer, sizeof(chars) - 1);
- TEST_TRUE(runner, Str_Equals_Utf8(thief, chars, sizeof(chars) - 1),
- "Str_new_steal_utf8");
- DECREF(thief);
- }
-
- {
- char *buffer = (char*)MALLOCATE(sizeof(chars));
- strcpy(buffer, chars);
- String *thief
- = Str_new_steal_trusted_utf8(buffer, sizeof(chars) - 1);
- TEST_TRUE(runner, Str_Equals_Utf8(thief, chars, sizeof(chars) - 1),
- "Str_new_steal_trusted_utf8");
- DECREF(thief);
- }
-
- {
- String *wrapper = Str_new_wrap_utf8(chars, sizeof(chars) - 1);
- TEST_TRUE(runner, Str_Equals_Utf8(wrapper, chars, sizeof(chars) - 1),
- "Str_new_wrap_utf8");
- DECREF(wrapper);
- }
-
- {
- String *wrapper = Str_new_wrap_trusted_utf8(chars, sizeof(chars) - 1);
- TEST_TRUE(runner, Str_Equals_Utf8(wrapper, chars, sizeof(chars) - 1),
- "Str_new_wrap_trusted_utf8");
- DECREF(wrapper);
- }
-
- {
- String *smiley_str = Str_new_from_char(smiley_cp);
- TEST_TRUE(runner, Str_Equals_Utf8(smiley_str, smiley, smiley_len),
- "Str_new_from_char");
- DECREF(smiley_str);
- }
-}
-
-static void
-test_Cat(TestBatchRunner *runner) {
- String *wanted = Str_newf("a%s", smiley);
- String *source;
- String *got;
-
- source = S_get_str("");
- got = Str_Cat(source, wanted);
- TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "Cat");
- DECREF(got);
- DECREF(source);
-
- source = S_get_str("a");
- got = Str_Cat_Utf8(source, smiley, smiley_len);
- TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "Cat_Utf8");
- DECREF(got);
- DECREF(source);
-
- source = S_get_str("a");
- got = Str_Cat_Trusted_Utf8(source, smiley, smiley_len);
- TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "Cat_Trusted_Utf8");
- DECREF(got);
- DECREF(source);
-
- DECREF(wanted);
-}
-
-static void
-test_Clone(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo");
- String *got = Str_Clone(wanted);
- TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "Clone");
- DECREF(got);
- DECREF(wanted);
-}
-
-static int64_t
-S_find(String *string, String *substring) {
- StringIterator *iter = Str_Find(string, substring);
- if (iter == NULL) { return -1; }
- size_t tick = StrIter_Recede(iter, SIZE_MAX);
- DECREF(iter);
- return (int64_t)tick;
-}
-
-static void
-test_Contains_and_Find(TestBatchRunner *runner) {
- String *string;
- String *substring = S_get_str("foo");
- String *empty = S_get_str("");
-
- TEST_FALSE(runner, Str_Contains(empty, substring),
- "Not contained in empty string");
- TEST_INT_EQ(runner, S_find(empty, substring), -1,
- "Not found in empty string");
-
- string = S_get_str("foo");
- TEST_TRUE(runner, Str_Contains(string, substring),
- "Contains complete string");
- TEST_INT_EQ(runner, S_find(string, substring), 0, "Find complete string");
- TEST_TRUE(runner, Str_Contains(string, empty),
- "Contains empty string");
- TEST_INT_EQ(runner, S_find(string, empty), 0, "Find empty string");
- DECREF(string);
-
- string = S_get_str("afoo");
- TEST_TRUE(runner, Str_Contains(string, substring),
- "Contained after first");
- TEST_INT_EQ(runner, S_find(string, substring), 1, "Find after first");
- String *prefix = Str_SubString(string, 0, 3);
- TEST_FALSE(runner, Str_Contains(prefix, substring), "Don't overrun");
- DECREF(prefix);
- DECREF(string);
-
- string = S_get_str("afood");
- TEST_TRUE(runner, Str_Contains(string, substring), "Contained in middle");
- TEST_INT_EQ(runner, S_find(string, substring), 1, "Find in middle");
- DECREF(string);
-
- DECREF(empty);
- DECREF(substring);
-}
-
-static void
-test_Code_Point_At_and_From(TestBatchRunner *runner) {
- int32_t code_points[] = {
- 'a', smiley_cp, smiley_cp, 'b', smiley_cp, 'c'
- };
- uint32_t num_code_points = sizeof(code_points) / sizeof(int32_t);
- String *string = Str_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;
- TEST_INT_EQ(runner, Str_Code_Point_At(string, i), code_points[i],
- "Code_Point_At %ld", (long)i);
- TEST_INT_EQ(runner, Str_Code_Point_From(string, from),
- code_points[i], "Code_Point_From %ld", (long)from);
- }
-
- TEST_INT_EQ(runner, Str_Code_Point_At(string, num_code_points), STR_OOB,
- "Code_Point_At %ld", (long)num_code_points);
- TEST_INT_EQ(runner, Str_Code_Point_From(string, 0), STR_OOB,
- "Code_Point_From 0");
- TEST_INT_EQ(runner, Str_Code_Point_From(string, num_code_points + 1),
- STR_OOB, "Code_Point_From %ld", (long)(num_code_points + 1));
-
- DECREF(string);
-}
-
-static void
-test_SubString(TestBatchRunner *runner) {
- {
- String *string = Str_newf("a%s%sb%sc", smiley, smiley, smiley);
- String *wanted = Str_newf("%sb%s", smiley, smiley);
- String *got = Str_SubString(string, 2, 3);
- TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "SubString");
- DECREF(string);
- DECREF(wanted);
- DECREF(got);
- }
-
- {
- static const char chars[] = "A string.";
- String *wrapper = Str_new_wrap_utf8(chars, sizeof(chars) - 1);
- String *wanted = Str_newf("string");
- String *got = Str_SubString(wrapper, 2, 6);
- TEST_TRUE(runner, Str_Equals(got, (Obj*)wanted),
- "SubString with wrapped buffer");
- DECREF(wrapper);
- DECREF(wanted);
- DECREF(got);
- }
-}
-
-static void
-test_Trim(TestBatchRunner *runner) {
- String *ws_smiley = S_smiley_with_whitespace(NULL);
- String *ws_foo = S_get_str(" foo ");
- String *ws_only = S_get_str(" \t \r\n");
- String *trimmed = S_get_str("a b");
- String *got;
-
- got = Str_Trim(ws_smiley);
- TEST_TRUE(runner, Str_Equals_Utf8(got, smiley, smiley_len), "Trim");
- DECREF(got);
-
- got = Str_Trim_Top(ws_foo);
- TEST_TRUE(runner, Str_Equals_Utf8(got, "foo ", 5), "Trim_Top");
- DECREF(got);
-
- got = Str_Trim_Tail(ws_foo);
- TEST_TRUE(runner, Str_Equals_Utf8(got, " foo", 5), "Trim_Tail");
- DECREF(got);
-
- got = Str_Trim(ws_only);
- TEST_TRUE(runner, Str_Equals_Utf8(got, "", 0), "Trim with only whitespace");
- DECREF(got);
-
- got = Str_Trim_Top(ws_only);
- TEST_TRUE(runner, Str_Equals_Utf8(got, "", 0),
- "Trim_Top with only whitespace");
- DECREF(got);
-
- got = Str_Trim_Tail(ws_only);
- TEST_TRUE(runner, Str_Equals_Utf8(got, "", 0),
- "Trim_Tail with only whitespace");
- DECREF(got);
-
- got = Str_Trim(trimmed);
- TEST_TRUE(runner, Str_Equals(got, (Obj*)trimmed),
- "Trim doesn't change trimmed string");
- DECREF(got);
-
- got = Str_Trim_Top(trimmed);
- TEST_TRUE(runner, Str_Equals(got, (Obj*)trimmed),
- "Trim_Top doesn't change trimmed string");
- DECREF(got);
-
- got = Str_Trim_Tail(trimmed);
- TEST_TRUE(runner, Str_Equals(got, (Obj*)trimmed),
- "Trim_Tail doesn't change trimmed string");
- DECREF(got);
-
- DECREF(trimmed);
- DECREF(ws_only);
- DECREF(ws_foo);
- DECREF(ws_smiley);
-}
-
-static void
-test_To_F64(TestBatchRunner *runner) {
- String *string;
-
- string = S_get_str("1.5");
- double difference = 1.5 - Str_To_F64(string);
- if (difference < 0) { difference = 0 - difference; }
- TEST_TRUE(runner, difference < 0.001, "To_F64");
- DECREF(string);
-
- string = S_get_str("-1.5");
- difference = 1.5 + Str_To_F64(string);
- if (difference < 0) { difference = 0 - difference; }
- TEST_TRUE(runner, difference < 0.001, "To_F64 negative");
- DECREF(string);
-
- // TODO: Enable this test when we have real substrings.
- /*string = S_get_str("1.59");
- double value_full = Str_To_F64(string);
- Str_Set_Size(string, 3);
- double value_short = Str_To_F64(string);
- TEST_TRUE(runner, value_short < value_full,
- "TO_F64 doesn't run past end of string");
- DECREF(string);*/
-}
-
-static void
-test_To_I64(TestBatchRunner *runner) {
- String *string;
-
- string = S_get_str("10");
- TEST_INT_EQ(runner, Str_To_I64(string), 10, "To_I64");
- DECREF(string);
-
- string = S_get_str("-10");
- TEST_INT_EQ(runner, Str_To_I64(string), -10, "To_I64 negative");
- DECREF(string);
-
- string = S_get_str("10.");
- TEST_INT_EQ(runner, Str_To_I64(string), 10, "To_I64 stops at non-digits");
- DECREF(string);
-
- string = S_get_str("10" SMILEY);
- TEST_INT_EQ(runner, Str_To_I64(string), 10, "To_I64 stops at non-ASCII");
- DECREF(string);
-
- string = S_get_str("10A");
- TEST_INT_EQ(runner, Str_To_I64(string), 10,
- "To_I64 stops at out-of-range digits");
- DECREF(string);
-}
-
-static void
-test_BaseX_To_I64(TestBatchRunner *runner) {
- String *string;
-
- string = S_get_str("-JJ");
- TEST_INT_EQ(runner, Str_BaseX_To_I64(string, 20), -399,
- "BaseX_To_I64 base 20");
- DECREF(string);
-}
-
-static void
-test_To_String(TestBatchRunner *runner) {
- String *string = Str_newf("Test");
- String *copy = Str_To_String(string);
- TEST_TRUE(runner, Str_Equals(copy, (Obj*)string), "To_String");
- DECREF(string);
- DECREF(copy);
-}
-
-static void
-test_To_Utf8(TestBatchRunner *runner) {
- String *string = Str_newf("a%s%sb%sc", smiley, smiley, smiley);
- char *buf = Str_To_Utf8(string);
- TEST_TRUE(runner, strcmp(buf, "a" SMILEY SMILEY "b" SMILEY "c") == 0,
- "To_Utf8");
- FREEMEM(buf);
- DECREF(string);
-}
-
-static void
-test_To_ByteBuf(TestBatchRunner *runner) {
- String *string = Str_newf("foo");
- ByteBuf *bb = Str_To_ByteBuf(string);
- TEST_TRUE(runner, BB_Equals_Bytes(bb, "foo", 3), "To_ByteBuf");
- DECREF(bb);
- DECREF(string);
-}
-
-static void
-test_Length(TestBatchRunner *runner) {
- String *string = Str_newf("a%s%sb%sc", smiley, smiley, smiley);
- TEST_UINT_EQ(runner, Str_Length(string), 6, "Length");
- DECREF(string);
-}
-
-static void
-test_Compare_To(TestBatchRunner *runner) {
- String *abc = Str_newf("a%s%sb%sc", smiley, smiley, smiley);
- String *ab = Str_newf("a%s%sb", smiley, smiley);
- String *ac = Str_newf("a%s%sc", smiley, smiley);
-
- TEST_TRUE(runner, Str_Compare_To(abc, (Obj*)abc) == 0,
- "Compare_To abc abc");
- TEST_TRUE(runner, Str_Compare_To(ab, (Obj*)abc) < 0,
- "Compare_To ab abc");
- TEST_TRUE(runner, Str_Compare_To(abc, (Obj*)ab) > 0,
- "Compare_To abc ab");
- TEST_TRUE(runner, Str_Compare_To(ab, (Obj*)ac) < 0,
- "Compare_To ab ac");
- TEST_TRUE(runner, Str_Compare_To(ac, (Obj*)ab) > 0,
- "Compare_To ac ab");
-
- DECREF(ac);
- DECREF(ab);
- DECREF(abc);
-}
-
-static void
-test_Starts_Ends_With(TestBatchRunner *runner) {
- String *prefix = S_get_str("pre" SMILEY "fix_");
- String *suffix = S_get_str("_post" SMILEY "fix");
- String *empty = S_get_str("");
-
- TEST_TRUE(runner, Str_Starts_With(suffix, suffix),
- "Starts_With self returns true");
- TEST_TRUE(runner, Str_Ends_With(prefix, prefix),
- "Ends_With self returns true");
-
- TEST_TRUE(runner, Str_Starts_With(suffix, empty),
- "Starts_With empty string returns true");
- TEST_TRUE(runner, Str_Ends_With(prefix, empty),
- "Ends_With empty string returns true");
- TEST_FALSE(runner, Str_Starts_With(empty, suffix),
- "Empty string Starts_With returns false");
- TEST_FALSE(runner, Str_Ends_With(empty, prefix),
- "Empty string Ends_With returns false");
-
- {
- String *string
- = S_get_str("pre" SMILEY "fix_string_post" SMILEY "fix");
- TEST_TRUE(runner, Str_Starts_With(string, prefix),
- "Starts_With returns true");
- TEST_TRUE(runner, Str_Ends_With(string, suffix),
- "Ends_With returns true");
- DECREF(string);
- }
-
- {
- String *string
- = S_get_str("pre" SMILEY "fix:string:post" SMILEY "fix");
- TEST_FALSE(runner, Str_Starts_With(string, prefix),
- "Starts_With returns false");
- TEST_FALSE(runner, Str_Ends_With(string, suffix),
- "Ends_With returns false");
- DECREF(string);
- }
-
- DECREF(prefix);
- DECREF(suffix);
- DECREF(empty);
-}
-
-static void
-test_Starts_Ends_With_Utf8(TestBatchRunner *runner) {
- String *str = S_get_str("pre" SMILEY "post");
-
- static const char prefix[] = "pre" SMILEY;
- static const char postfix[] = SMILEY "post";
- static const size_t prefix_size = sizeof(prefix) - 1;
- static const size_t postfix_size = sizeof(postfix) - 1;
- TEST_TRUE(runner, Str_Starts_With_Utf8(str, prefix, prefix_size),
- "Starts_With_Utf8 returns true");
- TEST_TRUE(runner, Str_Ends_With_Utf8(str, postfix, postfix_size),
- "Ends_With_Utf8 returns true");
- TEST_FALSE(runner, Str_Starts_With_Utf8(str, postfix, postfix_size),
- "Starts_With_Utf8 returns false");
- TEST_FALSE(runner, Str_Ends_With_Utf8(str, prefix, prefix_size),
- "Ends_With_Utf8 returns false");
-
- static const char longer[] = "12345678901234567890";
- static const size_t longer_size = sizeof(longer) - 1;
- TEST_FALSE(runner, Str_Starts_With_Utf8(str, longer, longer_size),
- "Starts_With_Utf8 longer str returns false");
- TEST_FALSE(runner, Str_Ends_With_Utf8(str, longer, longer_size),
- "Ends_With_Utf8 longer str returns false");
-
- DECREF(str);
-}
-
-static void
-test_Get_Ptr8(TestBatchRunner *runner) {
- String *string = S_get_str("Banana");
-
- const char *ptr8 = Str_Get_Ptr8(string);
- TEST_TRUE(runner, strcmp(ptr8, "Banana") == 0, "Get_Ptr8");
-
- size_t size = Str_Get_Size(string);
- TEST_UINT_EQ(runner, size, 6, "Get_Size");
-
- DECREF(string);
-}
-
-static void
-test_iterator(TestBatchRunner *runner) {
- static const int32_t code_points[] = {
- 0x41,
- 0x7F,
- 0x80,
- 0x7FF,
- 0x800,
- 0xFFFF,
- 0x10000,
- 0x10FFFF
- };
- static size_t num_code_points
- = sizeof(code_points) / sizeof(code_points[0]);
-
- CharBuf *buf = CB_new(0);
- for (size_t i = 0; i < num_code_points; ++i) {
- CB_Cat_Char(buf, code_points[i]);
- }
- String *string = CB_To_String(buf);
-
- {
- StringIterator *iter = Str_Top(string);
-
- TEST_TRUE(runner, StrIter_Equals(iter, (Obj*)iter),
- "StringIterator equal to self");
- TEST_FALSE(runner, StrIter_Equals(iter, (Obj*)CFISH_TRUE),
- "StringIterator not equal non-iterators");
-
- DECREF(iter);
- }
-
- {
- StringIterator *top = Str_Top(string);
- StringIterator *tail = Str_Tail(string);
-
- TEST_FALSE(runner, StrIter_Equals(top, (Obj*)tail),
- "StrIter_Equals returns false");
-
- TEST_INT_EQ(runner, StrIter_Compare_To(top, (Obj*)tail), -1,
- "Compare_To top < tail");
- TEST_INT_EQ(runner, StrIter_Compare_To(tail, (Obj*)top), 1,
- "Compare_To tail > top");
- TEST_INT_EQ(runner, StrIter_Compare_To(top, (Obj*)top), 0,
- "Compare_To top == top");
-
- StringIterator *clone = StrIter_Clone(top);
- TEST_TRUE(runner, StrIter_Equals(clone, (Obj*)top), "Clone");
-
- StrIter_Assign(clone, tail);
- TEST_TRUE(runner, StrIter_Equals(clone, (Obj*)tail), "Assign");
-
- String *other = Str_newf("Other string");
- StringIterator *other_iter = Str_Top(other);
- TEST_FALSE(runner, StrIter_Equals(other_iter, (Obj*)tail),
- "Equals returns false for different strings");
- StrIter_Assign(clone, other_iter);
- TEST_TRUE(runner, StrIter_Equals(clone, (Obj*)other_iter),
- "Assign iterator with different string");
-
- DECREF(other);
- DECREF(other_iter);
- DECREF(clone);
- DECREF(top);
- DECREF(tail);
- }
-
- {
- StringIterator *iter = Str_Top(string);
-
- for (size_t i = 0; i < num_code_points; ++i) {
- TEST_TRUE(runner, StrIter_Has_Next(iter), "Has_Next %d", i);
- int32_t code_point = StrIter_Next(iter);
- TEST_INT_EQ(runner, code_point, code_points[i], "Next %d", i);
- }
-
- TEST_TRUE(runner, !StrIter_Has_Next(iter),
- "Has_Next at end of string");
- TEST_INT_EQ(runner, StrIter_Next(iter), STR_OOB,
- "Next at end of string");
-
- StringIterator *tail = Str_Tail(string);
- TEST_TRUE(runner, StrIter_Equals(iter, (Obj*)tail), "Equals tail");
-
- DECREF(tail);
- DECREF(iter);
- }
-
- {
- StringIterator *iter = Str_Tail(string);
-
- for (size_t i = num_code_points; i--;) {
- TEST_TRUE(runner, StrIter_Has_Prev(iter), "Has_Prev %d", i);
- int32_t code_point = StrIter_Prev(iter);
- TEST_INT_EQ(runner, code_point, code_points[i], "Prev %d", i);
- }
-
- TEST_TRUE(runner, !StrIter_Has_Prev(iter),
- "Has_Prev at end of string");
- TEST_INT_EQ(runner, StrIter_Prev(iter), STR_OOB,
- "Prev at start of string");
-
- StringIterator *top = Str_Top(string);
- TEST_TRUE(runner, StrIter_Equals(iter, (Obj*)top), "Equals top");
-
- DECREF(top);
- DECREF(iter);
- }
-
- {
- StringIterator *iter = Str_Top(string);
-
- StrIter_Next(iter);
- TEST_UINT_EQ(runner, StrIter_Advance(iter, 2), 2,
- "Advance returns number of code points");
- TEST_INT_EQ(runner, StrIter_Next(iter), code_points[3],
- "Advance works");
- TEST_UINT_EQ(runner,
- StrIter_Advance(iter, 1000000), num_code_points - 4,
- "Advance past end of string");
-
- StrIter_Prev(iter);
- TEST_UINT_EQ(runner, StrIter_Recede(iter, 2), 2,
- "Recede returns number of code points");
- TEST_INT_EQ(runner, StrIter_Prev(iter), code_points[num_code_points-4],
- "Recede works");
- TEST_UINT_EQ(runner, StrIter_Recede(iter, 1000000), num_code_points - 4,
- "Recede past start of string");
-
- DECREF(iter);
- }
-
- DECREF(string);
- DECREF(buf);
-}
-
-static void
-test_iterator_whitespace(TestBatchRunner *runner) {
- size_t num_spaces;
- String *ws_smiley = S_smiley_with_whitespace(&num_spaces);
-
- {
- StringIterator *iter = Str_Top(ws_smiley);
- TEST_UINT_EQ(runner, StrIter_Skip_Whitespace(iter), num_spaces,
- "Skip_Whitespace");
- TEST_UINT_EQ(runner, StrIter_Skip_Whitespace(iter), 0,
- "Skip_Whitespace without whitespace");
- DECREF(iter);
- }
-
- {
- StringIterator *iter = Str_Tail(ws_smiley);
- TEST_UINT_EQ(runner, StrIter_Skip_Whitespace_Back(iter), num_spaces,
- "Skip_Whitespace_Back");
- TEST_UINT_EQ(runner, StrIter_Skip_Whitespace_Back(iter), 0,
- "Skip_Whitespace_Back without whitespace");
- DECREF(iter);
- }
-
- DECREF(ws_smiley);
-}
-
-typedef struct {
- StringIterator *top;
- StringIterator *tail;
-} StrIterCropContext;
-
-static void
-S_striter_crop(void *vcontext) {
- StrIterCropContext *context = (StrIterCropContext*)vcontext;
- StrIter_crop(context->top, context->tail);
-}
-
-static void
-test_iterator_substring(TestBatchRunner *runner) {
- String *string = Str_newf("a%sb%sc%sd", smiley, smiley, smiley);
-
- StringIterator *start = Str_Top(string);
- StringIterator *end = Str_Tail(string);
-
- {
- String *substring = StrIter_crop(start, end);
- TEST_TRUE(runner, Str_Equals(substring, (Obj*)string),
- "StrIter_crop whole string");
- DECREF(substring);
- }
-
- StrIter_Advance(start, 2);
- StrIter_Recede(end, 2);
-
- {
- String *substring = StrIter_crop(start, end);
- static const char wanted_buf[] = "b" SMILEY "c";
- static const size_t wanted_size = sizeof(wanted_buf) - 1;
- String *wanted = Str_new_from_utf8(wanted_buf, wanted_size);
- TEST_TRUE(runner, Str_Equals(substring, (Obj*)wanted),
- "StrIter_crop");
-
- TEST_TRUE(runner, StrIter_Starts_With(start, wanted),
- "Starts_With returns true");
- TEST_TRUE(runner, StrIter_Ends_With(end, wanted),
- "Ends_With returns true");
- TEST_TRUE(runner,
- StrIter_Starts_With_Utf8(start, wanted_buf, wanted_size),
- "Starts_With_Utf8 returns true");
- TEST_TRUE(runner,
- StrIter_Ends_With_Utf8(end, wanted_buf, wanted_size),
- "Ends_With_Utf8 returns true");
-
- DECREF(wanted);
- DECREF(substring);
- }
-
- {
- static const char short_buf[] = "b" SMILEY "x";
- static const size_t short_size = sizeof(short_buf) - 1;
- String *short_str = Str_new_from_utf8(short_buf, short_size);
- TEST_FALSE(runner, StrIter_Starts_With(start, short_str),
- "Starts_With returns false");
- TEST_FALSE(runner, StrIter_Ends_With(start, short_str),
- "Ends_With returns false");
- TEST_FALSE(runner,
- StrIter_Starts_With_Utf8(start, short_buf, short_size),
- "Starts_With_Utf8 returns false");
- TEST_FALSE(runner,
- StrIter_Ends_With_Utf8(start, short_buf, short_size),
- "Ends_With_Utf8 returns false");
-
- static const char long_buf[] = "b" SMILEY "xxxxxxxxxxxx" SMILEY "c";
- static const size_t long_size = sizeof(long_buf) - 1;
- String *long_str = Str_new_from_utf8(long_buf, long_size);
- TEST_FALSE(runner, StrIter_Starts_With(start, long_str),
- "Starts_With long string returns false");
- TEST_FALSE(runner, StrIter_Ends_With(end, long_str),
- "Ends_With long string returns false");
- TEST_FALSE(runner,
- StrIter_Starts_With_Utf8(start, long_buf, long_size),
- "Starts_With_Utf8 long string returns false");
- TEST_FALSE(runner,
- StrIter_Ends_With_Utf8(end, long_buf, long_size),
- "Ends_With_Utf8 long string returns false");
-
- DECREF(short_str);
- DECREF(long_str);
- }
-
- {
- String *substring = StrIter_crop(end, NULL);
- String *wanted = Str_newf("%sd", smiley);
- TEST_TRUE(runner, Str_Equals(substring, (Obj*)wanted),
- "StrIter_crop with NULL tail");
- DECREF(wanted);
- DECREF(substring);
- }
-
- {
- String *substring = StrIter_crop(NULL, start);
- String *wanted = Str_newf("a%s", smiley);
- TEST_TRUE(runner, Str_Equals(substring, (Obj*)wanted),
- "StrIter_crop with NULL top");
- DECREF(wanted);
- DECREF(substring);
- }
-
- {
- StrIterCropContext context;
- context.top = NULL;
- context.tail = NULL;
- Err *error = Err_trap(S_striter_crop, &context);
- TEST_TRUE(runner, error != NULL,
- "StrIter_crop throws if top and tail are NULL");
- DECREF(error);
- }
-
- {
- String *other = SSTR_WRAP_C("other");
- StrIterCropContext context;
- context.top = start;
- context.tail = Str_Tail(other);
- Err *error = Err_trap(S_striter_crop, &context);
- TEST_TRUE(runner, error != NULL,
- "StrIter_crop throws if string don't match");
- DECREF(error);
- DECREF(context.tail);
- }
-
- {
- StrIterCropContext context;
- context.top = end;
- context.tail = start;
- Err *error = Err_trap(S_striter_crop, &context);
- TEST_TRUE(runner, error != NULL,
- "StrIter_crop throws if top is behind tail");
- DECREF(error);
- }
-
- DECREF(start);
- DECREF(end);
- DECREF(string);
-}
-
-void
-TestStr_Run_IMP(TestString *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 158);
- test_new(runner);
- test_Cat(runner);
- test_Clone(runner);
- test_Code_Point_At_and_From(runner);
- test_Contains_and_Find(runner);
- test_SubString(runner);
- test_Trim(runner);
- test_To_F64(runner);
- test_To_I64(runner);
- test_BaseX_To_I64(runner);
- test_To_String(runner);
- test_To_Utf8(runner);
- test_To_ByteBuf(runner);
- test_Length(runner);
- test_Compare_To(runner);
- test_Starts_Ends_With(runner);
- test_Starts_Ends_With_Utf8(runner);
- test_Get_Ptr8(runner);
- test_iterator(runner);
- test_iterator_whitespace(runner);
- test_iterator_substring(runner);
-}
-
-/*************************** StringCallbackTest ***************************/
-
-bool
-StrCbTest_Unchanged_By_Callback_IMP(StringCallbackTest *self, String *str) {
- String *before = Str_Clone(str);
- StrCbTest_Callback(self);
- return Str_Equals(str, (Obj*)before);
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestString.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestString.cfh b/runtime/core/Clownfish/Test/TestString.cfh
deleted file mode 100644
index 88e43c9..0000000
--- a/runtime/core/Clownfish/Test/TestString.cfh
+++ /dev/null
@@ -1,36 +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 TestClownfish;
-
-class Clownfish::Test::TestString nickname TestStr
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestString*
- new();
-
- void
- Run(TestString *self, TestBatchRunner *runner);
-}
-
-abstract class Clownfish::Test::StringCallbackTest nickname StrCbTest {
- bool
- Unchanged_By_Callback(StringCallbackTest *self, String *str);
-
- abstract void
- Callback(StringCallbackTest *self);
-}
-
[10/14] lucy-clownfish git commit: Separate test binaries
Posted by nw...@apache.org.
Separate test binaries
The C bindings build a separate shared library libcfishtest.so.
Building a static library would simplify things a little but would
require another per-parcel macro on Windows (like
CFP_STATIC_TESTCFISH).
The Perl bindings build a separate XS module Clownfish::Test.
For the Go and Python bindings, a separate static library
libtestcfish.a is built.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/ef738c21
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/ef738c21
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/ef738c21
Branch: refs/heads/master
Commit: ef738c212adbed879cc75ab49675deae4f6e8b04
Parents: a80e405
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 8 13:57:30 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 8 14:29:42 2016 +0200
----------------------------------------------------------------------
runtime/c/.gitignore | 21 +--
runtime/common/charmonizer.c | 157 ++++++++++++------
runtime/common/charmonizer.main | 159 +++++++++++++------
runtime/go/build.go | 3 +-
runtime/perl/.gitignore | 2 +
runtime/perl/buildlib/Clownfish/Build.pm | 8 +-
.../perl/buildlib/Clownfish/Build/Binding.pm | 2 +-
runtime/perl/lib/Clownfish/Test.pm | 8 +
runtime/perl/t/binding/019-obj.t | 1 +
runtime/perl/t/binding/023-string.t | 1 +
runtime/python/setup.py | 11 +-
11 files changed, 253 insertions(+), 120 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/c/.gitignore
----------------------------------------------------------------------
diff --git a/runtime/c/.gitignore b/runtime/c/.gitignore
index 641de1e..724f367 100644
--- a/runtime/c/.gitignore
+++ b/runtime/c/.gitignore
@@ -1,18 +1,13 @@
+*.dll
+*.dll.a
+*.dylib
+*.exe
+*.exp
+*.lib
+*.so
+*.so.*
/Makefile
/autogen/
-/cfish-*.dll
-/cfish-*.exp
-/cfish-*.lib
/charmonizer
-/charmonizer.exe
/charmony.h
-/cygcfish-*.dll
-/libcfish-*.dll
-/libcfish.*.dylib
-/libcfish.a
-/libcfish.a.*
-/libcfish.dylib
-/libcfish.so
-/libcfish.so.*
/t/test_cfish
-/t/test_cfish.exe
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.c b/runtime/common/charmonizer.c
index af37cfd..37cfaf4 100644
--- a/runtime/common/charmonizer.c
+++ b/runtime/common/charmonizer.c
@@ -8589,7 +8589,8 @@ chaz_VariadicMacros_run(void) {
typedef struct cfish_MakeFile {
chaz_MakeFile *makefile;
- chaz_MakeBinary *binary;
+ chaz_MakeBinary *lib;
+ chaz_MakeBinary *test_lib;
chaz_MakeVar *cfh_var;
chaz_CLI *cli;
@@ -8804,7 +8805,8 @@ cfish_MakeFile_new(chaz_CLI *cli) {
cfish_MakeFile *self = malloc(sizeof(cfish_MakeFile));
self->makefile = chaz_MakeFile_new();
- self->binary = NULL;
+ self->lib = NULL;
+ self->test_lib = NULL;
self->cfh_var = NULL;
self->cli = cli;
@@ -8851,15 +8853,12 @@ cfish_MakeFile_destroy(cfish_MakeFile *self) {
static void
cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
- static const char *const autogen_src_files[] = {
- "cfish_parcel.c",
- "testcfish_parcel.c",
- NULL
- };
-
const char *dir_sep = chaz_OS_dir_sep();
const char *host = chaz_CLI_strval(self->cli, "host");
+ const char *lib_objs = NULL;
+ const char *test_lib_objs = NULL;
+
chaz_MakeVar *var;
chaz_MakeRule *rule;
@@ -8868,8 +8867,6 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
chaz_CFlags *compile_flags;
chaz_CFlags *link_flags;
- int i;
-
printf("Creating Makefile...\n");
/* Directories */
@@ -8903,77 +8900,119 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
chaz_CFlags_destroy(makefile_cflags);
- /* Binary. */
+ /* Core library. */
if (strcmp(host, "c") == 0 || strcmp(host, "perl") == 0) {
+ /* Shared library for C and Perl. */
+
chaz_MakeFile_add_rule(self->makefile, "all", "$(CFISH_SHARED_LIB)");
- self->binary
+ self->lib
= chaz_MakeFile_add_shared_lib(self->makefile, NULL, "cfish",
cfish_version, cfish_major_version);
- chaz_MakeFile_add_rule(self->makefile, "$(CFISH_SHARED_LIB_OBJS)",
- self->autogen_target);
+ lib_objs = "$(CFISH_SHARED_LIB_OBJS)";
+
+ compile_flags = chaz_MakeBinary_get_compile_flags(self->lib);
+ chaz_CFlags_add_define(compile_flags, "CFP_CFISH", NULL);
+
+ link_flags = chaz_MakeBinary_get_link_flags(self->lib);
+ chaz_CFlags_enable_debugging(link_flags);
+ chaz_CFlags_append(link_flags,
+ chaz_CFlags_get_string(extra_link_flags));
}
else {
+ /* Static library for Go and Python. */
+
chaz_MakeFile_add_rule(self->makefile, "static",
- "$(CLOWNFISH_STATIC_LIB)");
+ "$(CLOWNFISH_STATIC_LIB)"
+ " $(TESTCFISH_STATIC_LIB)");
- self->binary
+ self->lib
= chaz_MakeFile_add_static_lib(self->makefile, NULL, "clownfish");
- chaz_MakeFile_add_rule(self->makefile, "$(CLOWNFISH_STATIC_LIB_OBJS)",
- self->autogen_target);
+ lib_objs = "$(CLOWNFISH_STATIC_LIB_OBJS)";
}
if (self->host_src_dir) {
- chaz_MakeBinary_add_src_dir(self->binary, self->host_src_dir);
+ chaz_MakeBinary_add_src_dir(self->lib, self->host_src_dir);
}
- chaz_MakeBinary_add_src_dir(self->binary, self->core_dir);
- chaz_MakeBinary_add_src_dir(self->binary, self->test_dir);
+ chaz_MakeBinary_add_src_dir(self->lib, self->core_dir);
+ chaz_MakeBinary_add_src_file(self->lib, self->autogen_src_dir,
+ "cfish_parcel.c");
+
+ /* Test library. */
- compile_flags = chaz_MakeBinary_get_compile_flags(self->binary);
- chaz_CFlags_add_define(compile_flags, "CFP_CFISH", NULL);
- chaz_CFlags_add_define(compile_flags, "CFP_TESTCFISH", NULL);
+ if (strcmp(host, "c") == 0 || strcmp(host, "perl") == 0) {
+ /* Shared library for C and Perl. */
+
+ self->test_lib
+ = chaz_MakeFile_add_shared_lib(self->makefile, NULL, "testcfish",
+ cfish_version, cfish_major_version);
+ test_lib_objs = "$(TESTCFISH_SHARED_LIB_OBJS)";
- link_flags = chaz_MakeBinary_get_link_flags(self->binary);
- chaz_CFlags_enable_debugging(link_flags);
- chaz_CFlags_append(link_flags, chaz_CFlags_get_string(extra_link_flags));
+ compile_flags = chaz_MakeBinary_get_compile_flags(self->test_lib);
+ chaz_CFlags_add_define(compile_flags, "CFP_TESTCFISH", NULL);
- for (i = 0; autogen_src_files[i] != NULL; ++i) {
- chaz_MakeBinary_add_src_file(self->binary, self->autogen_src_dir,
- autogen_src_files[i]);
+ link_flags = chaz_MakeBinary_get_link_flags(self->test_lib);
+ chaz_CFlags_enable_debugging(link_flags);
+ chaz_CFlags_append(link_flags,
+ chaz_CFlags_get_string(extra_link_flags));
+ chaz_CFlags_add_shared_lib(link_flags, NULL, "cfish",
+ cfish_major_version);
+
+ chaz_MakeBinary_add_prereq(self->test_lib, "$(CFISH_SHARED_LIB)");
+ }
+ else {
+ /* Static library for Go and Python. */
+
+ self->test_lib
+ = chaz_MakeFile_add_static_lib(self->makefile, NULL, "testcfish");
+ test_lib_objs = "$(TESTCFISH_STATIC_LIB_OBJS)";
}
+ chaz_MakeBinary_add_src_dir(self->test_lib, self->test_dir);
+ chaz_MakeBinary_add_src_file(self->test_lib, self->autogen_src_dir,
+ "testcfish_parcel.c");
+
/* Additional rules. */
+ /* Object files depend on autogenerated headers. */
+ chaz_MakeFile_add_rule(self->makefile, lib_objs, self->autogen_target);
+ chaz_MakeFile_add_rule(self->makefile, test_lib_objs,
+ self->autogen_target);
+
if (strcmp(host, "c") == 0) {
cfish_MakeFile_write_c_cfc_rules(self);
cfish_MakeFile_write_c_test_rules(self);
}
+ /* Targets to compile object files for Perl. */
if (strcmp(host, "perl") == 0) {
- char *core_objects = chaz_MakeBinary_obj_string(self->binary);
+ char *objects;
+
chaz_MakeFile_add_rule(self->makefile, "core_objects",
"$(CFISH_SHARED_LIB_OBJS)");
- chaz_ConfWriter_add_def("CORE_OBJECTS", core_objects);
- free(core_objects);
- }
+ objects = chaz_MakeBinary_obj_string(self->lib);
+ chaz_ConfWriter_add_def("CORE_OBJECTS", objects);
+ free(objects);
- /* Needed for parallel builds. */
- for (i = 0; autogen_src_files[i] != NULL; ++i) {
- char *path = chaz_Util_join(dir_sep, self->autogen_src_dir,
- autogen_src_files[i], NULL);
- chaz_MakeFile_add_rule(self->makefile, path, self->autogen_target);
- free(path);
+ chaz_MakeFile_add_rule(self->makefile, "test_objects",
+ "$(TESTCFISH_SHARED_LIB_OBJS)");
+ objects = chaz_MakeBinary_obj_string(self->test_lib);
+ chaz_ConfWriter_add_def("TEST_OBJECTS", objects);
+ free(objects);
}
- rule = chaz_MakeFile_clean_rule(self->makefile);
- chaz_MakeRule_add_recursive_rm_command(rule, "autogen");
-
chaz_MakeFile_write(self->makefile);
}
static void
cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
+ static const char *const autogen_src_files[] = {
+ "cfish_parcel.c",
+ "testcfish_parcel.c",
+ NULL
+ };
+
chaz_MakeRule *rule;
const char *dir_sep = chaz_OS_dir_sep();
@@ -8983,6 +9022,8 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
char *cfc_exe;
char *cfc_command;
+ int i;
+
cfc_dir = chaz_Util_join(dir_sep, self->base_dir, "..", "compiler", "c",
NULL);
cfc_exe = chaz_Util_join("", cfc_dir, dir_sep, "cfc", exe_ext, NULL);
@@ -8995,14 +9036,24 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, self);
chaz_Make_list_files(self->test_dir, "cfh", S_cfh_file_callback, self);
- rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target, cfc_exe);
+ rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target,
+ cfc_exe);
chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
cfc_command = chaz_Util_join("", cfc_exe, " --source=", self->core_dir,
" --source=", self->test_dir,
" --dest=autogen --header=cfc_header", NULL);
chaz_MakeRule_add_command(rule, cfc_command);
+ /* Tell make how autogenerated source files are built. */
+ for (i = 0; autogen_src_files[i] != NULL; ++i) {
+ char *path = chaz_Util_join(dir_sep, self->autogen_src_dir,
+ autogen_src_files[i], NULL);
+ chaz_MakeFile_add_rule(self->makefile, path, self->autogen_target);
+ free(path);
+ }
+
rule = chaz_MakeFile_clean_rule(self->makefile);
+ chaz_MakeRule_add_recursive_rm_command(rule, "autogen");
chaz_MakeRule_add_make_command(rule, cfc_dir, "clean");
rule = chaz_MakeFile_distclean_rule(self->makefile);
@@ -9016,19 +9067,25 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
static void
cfish_MakeFile_write_c_test_rules(cfish_MakeFile *self) {
chaz_MakeBinary *exe;
- chaz_CFlags *link_cflags;
+ chaz_CFlags *link_flags;
chaz_MakeRule *rule;
exe = chaz_MakeFile_add_exe(self->makefile, "t", "test_cfish");
chaz_MakeBinary_add_src_file(exe, "t", "test_cfish.c");
- chaz_MakeFile_add_rule(self->makefile, "$(TEST_CFISH_EXE_OBJS)",
- self->autogen_target);
- link_cflags = chaz_MakeBinary_get_link_flags(exe);
- chaz_CFlags_add_shared_lib(link_cflags, NULL, "cfish",
+
+ link_flags = chaz_MakeBinary_get_link_flags(exe);
+ chaz_CFlags_add_rpath(link_flags, "\"$$PWD\"");
+ chaz_CFlags_add_shared_lib(link_flags, NULL, "testcfish",
cfish_major_version);
- chaz_CFlags_add_rpath(link_cflags, "\"$$PWD\"");
+ chaz_CFlags_add_shared_lib(link_flags, NULL, "cfish",
+ cfish_major_version);
+
+ chaz_MakeBinary_add_prereq(exe, "$(TESTCFISH_SHARED_LIB)");
chaz_MakeBinary_add_prereq(exe, "$(CFISH_SHARED_LIB)");
+ chaz_MakeFile_add_rule(self->makefile, "$(TEST_CFISH_EXE_OBJS)",
+ self->autogen_target);
+
rule = chaz_MakeFile_add_rule(self->makefile, "test", "$(TEST_CFISH_EXE)");
chaz_MakeRule_add_command(rule, "$(TEST_CFISH_EXE)");
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.main b/runtime/common/charmonizer.main
index 7ceb2dd..124541c 100644
--- a/runtime/common/charmonizer.main
+++ b/runtime/common/charmonizer.main
@@ -41,7 +41,8 @@
typedef struct cfish_MakeFile {
chaz_MakeFile *makefile;
- chaz_MakeBinary *binary;
+ chaz_MakeBinary *lib;
+ chaz_MakeBinary *test_lib;
chaz_MakeVar *cfh_var;
chaz_CLI *cli;
@@ -256,7 +257,8 @@ cfish_MakeFile_new(chaz_CLI *cli) {
cfish_MakeFile *self = malloc(sizeof(cfish_MakeFile));
self->makefile = chaz_MakeFile_new();
- self->binary = NULL;
+ self->lib = NULL;
+ self->test_lib = NULL;
self->cfh_var = NULL;
self->cli = cli;
@@ -303,15 +305,12 @@ cfish_MakeFile_destroy(cfish_MakeFile *self) {
static void
cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
- static const char *const autogen_src_files[] = {
- "cfish_parcel.c",
- "testcfish_parcel.c",
- NULL
- };
-
const char *dir_sep = chaz_OS_dir_sep();
const char *host = chaz_CLI_strval(self->cli, "host");
+ const char *lib_objs = NULL;
+ const char *test_lib_objs = NULL;
+
chaz_MakeVar *var;
chaz_MakeRule *rule;
@@ -320,8 +319,6 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
chaz_CFlags *compile_flags;
chaz_CFlags *link_flags;
- int i;
-
printf("Creating Makefile...\n");
/* Directories */
@@ -355,77 +352,119 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
chaz_CFlags_destroy(makefile_cflags);
- /* Binary. */
+ /* Core library. */
if (strcmp(host, "c") == 0 || strcmp(host, "perl") == 0) {
+ /* Shared library for C and Perl. */
+
chaz_MakeFile_add_rule(self->makefile, "all", "$(CFISH_SHARED_LIB)");
- self->binary
+ self->lib
= chaz_MakeFile_add_shared_lib(self->makefile, NULL, "cfish",
cfish_version, cfish_major_version);
- chaz_MakeFile_add_rule(self->makefile, "$(CFISH_SHARED_LIB_OBJS)",
- self->autogen_target);
+ lib_objs = "$(CFISH_SHARED_LIB_OBJS)";
+
+ compile_flags = chaz_MakeBinary_get_compile_flags(self->lib);
+ chaz_CFlags_add_define(compile_flags, "CFP_CFISH", NULL);
+
+ link_flags = chaz_MakeBinary_get_link_flags(self->lib);
+ chaz_CFlags_enable_debugging(link_flags);
+ chaz_CFlags_append(link_flags,
+ chaz_CFlags_get_string(extra_link_flags));
}
else {
+ /* Static library for Go and Python. */
+
chaz_MakeFile_add_rule(self->makefile, "static",
- "$(CLOWNFISH_STATIC_LIB)");
+ "$(CLOWNFISH_STATIC_LIB)"
+ " $(TESTCFISH_STATIC_LIB)");
- self->binary
+ self->lib
= chaz_MakeFile_add_static_lib(self->makefile, NULL, "clownfish");
- chaz_MakeFile_add_rule(self->makefile, "$(CLOWNFISH_STATIC_LIB_OBJS)",
- self->autogen_target);
+ lib_objs = "$(CLOWNFISH_STATIC_LIB_OBJS)";
}
if (self->host_src_dir) {
- chaz_MakeBinary_add_src_dir(self->binary, self->host_src_dir);
+ chaz_MakeBinary_add_src_dir(self->lib, self->host_src_dir);
}
- chaz_MakeBinary_add_src_dir(self->binary, self->core_dir);
- chaz_MakeBinary_add_src_dir(self->binary, self->test_dir);
+ chaz_MakeBinary_add_src_dir(self->lib, self->core_dir);
+ chaz_MakeBinary_add_src_file(self->lib, self->autogen_src_dir,
+ "cfish_parcel.c");
- compile_flags = chaz_MakeBinary_get_compile_flags(self->binary);
- chaz_CFlags_add_define(compile_flags, "CFP_CFISH", NULL);
- chaz_CFlags_add_define(compile_flags, "CFP_TESTCFISH", NULL);
+ /* Test library. */
- link_flags = chaz_MakeBinary_get_link_flags(self->binary);
- chaz_CFlags_enable_debugging(link_flags);
- chaz_CFlags_append(link_flags, chaz_CFlags_get_string(extra_link_flags));
+ if (strcmp(host, "c") == 0 || strcmp(host, "perl") == 0) {
+ /* Shared library for C and Perl. */
- for (i = 0; autogen_src_files[i] != NULL; ++i) {
- chaz_MakeBinary_add_src_file(self->binary, self->autogen_src_dir,
- autogen_src_files[i]);
+ self->test_lib
+ = chaz_MakeFile_add_shared_lib(self->makefile, NULL, "testcfish",
+ cfish_version, cfish_major_version);
+ test_lib_objs = "$(TESTCFISH_SHARED_LIB_OBJS)";
+
+ compile_flags = chaz_MakeBinary_get_compile_flags(self->test_lib);
+ chaz_CFlags_add_define(compile_flags, "CFP_TESTCFISH", NULL);
+
+ link_flags = chaz_MakeBinary_get_link_flags(self->test_lib);
+ chaz_CFlags_enable_debugging(link_flags);
+ chaz_CFlags_append(link_flags,
+ chaz_CFlags_get_string(extra_link_flags));
+ chaz_CFlags_add_shared_lib(link_flags, NULL, "cfish",
+ cfish_major_version);
+
+ chaz_MakeBinary_add_prereq(self->test_lib, "$(CFISH_SHARED_LIB)");
}
+ else {
+ /* Static library for Go and Python. */
+
+ self->test_lib
+ = chaz_MakeFile_add_static_lib(self->makefile, NULL, "testcfish");
+ test_lib_objs = "$(TESTCFISH_STATIC_LIB_OBJS)";
+ }
+
+ chaz_MakeBinary_add_src_dir(self->test_lib, self->test_dir);
+ chaz_MakeBinary_add_src_file(self->test_lib, self->autogen_src_dir,
+ "testcfish_parcel.c");
/* Additional rules. */
+ /* Object files depend on autogenerated headers. */
+ chaz_MakeFile_add_rule(self->makefile, lib_objs, self->autogen_target);
+ chaz_MakeFile_add_rule(self->makefile, test_lib_objs,
+ self->autogen_target);
+
if (strcmp(host, "c") == 0) {
cfish_MakeFile_write_c_cfc_rules(self);
cfish_MakeFile_write_c_test_rules(self);
}
+ /* Targets to compile object files for Perl. */
if (strcmp(host, "perl") == 0) {
- char *core_objects = chaz_MakeBinary_obj_string(self->binary);
+ char *objects;
+
chaz_MakeFile_add_rule(self->makefile, "core_objects",
"$(CFISH_SHARED_LIB_OBJS)");
- chaz_ConfWriter_add_def("CORE_OBJECTS", core_objects);
- free(core_objects);
- }
-
- /* Needed for parallel builds. */
- for (i = 0; autogen_src_files[i] != NULL; ++i) {
- char *path = chaz_Util_join(dir_sep, self->autogen_src_dir,
- autogen_src_files[i], NULL);
- chaz_MakeFile_add_rule(self->makefile, path, self->autogen_target);
- free(path);
+ objects = chaz_MakeBinary_obj_string(self->lib);
+ chaz_ConfWriter_add_def("CORE_OBJECTS", objects);
+ free(objects);
+
+ chaz_MakeFile_add_rule(self->makefile, "test_objects",
+ "$(TESTCFISH_SHARED_LIB_OBJS)");
+ objects = chaz_MakeBinary_obj_string(self->test_lib);
+ chaz_ConfWriter_add_def("TEST_OBJECTS", objects);
+ free(objects);
}
- rule = chaz_MakeFile_clean_rule(self->makefile);
- chaz_MakeRule_add_recursive_rm_command(rule, "autogen");
-
chaz_MakeFile_write(self->makefile);
}
static void
cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
+ static const char *const autogen_src_files[] = {
+ "cfish_parcel.c",
+ "testcfish_parcel.c",
+ NULL
+ };
+
chaz_MakeRule *rule;
const char *dir_sep = chaz_OS_dir_sep();
@@ -435,6 +474,8 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
char *cfc_exe;
char *cfc_command;
+ int i;
+
cfc_dir = chaz_Util_join(dir_sep, self->base_dir, "..", "compiler", "c",
NULL);
cfc_exe = chaz_Util_join("", cfc_dir, dir_sep, "cfc", exe_ext, NULL);
@@ -447,14 +488,24 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, self);
chaz_Make_list_files(self->test_dir, "cfh", S_cfh_file_callback, self);
- rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target, cfc_exe);
+ rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target,
+ cfc_exe);
chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
cfc_command = chaz_Util_join("", cfc_exe, " --source=", self->core_dir,
" --source=", self->test_dir,
" --dest=autogen --header=cfc_header", NULL);
chaz_MakeRule_add_command(rule, cfc_command);
+ /* Tell make how autogenerated source files are built. */
+ for (i = 0; autogen_src_files[i] != NULL; ++i) {
+ char *path = chaz_Util_join(dir_sep, self->autogen_src_dir,
+ autogen_src_files[i], NULL);
+ chaz_MakeFile_add_rule(self->makefile, path, self->autogen_target);
+ free(path);
+ }
+
rule = chaz_MakeFile_clean_rule(self->makefile);
+ chaz_MakeRule_add_recursive_rm_command(rule, "autogen");
chaz_MakeRule_add_make_command(rule, cfc_dir, "clean");
rule = chaz_MakeFile_distclean_rule(self->makefile);
@@ -468,19 +519,25 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
static void
cfish_MakeFile_write_c_test_rules(cfish_MakeFile *self) {
chaz_MakeBinary *exe;
- chaz_CFlags *link_cflags;
+ chaz_CFlags *link_flags;
chaz_MakeRule *rule;
exe = chaz_MakeFile_add_exe(self->makefile, "t", "test_cfish");
chaz_MakeBinary_add_src_file(exe, "t", "test_cfish.c");
- chaz_MakeFile_add_rule(self->makefile, "$(TEST_CFISH_EXE_OBJS)",
- self->autogen_target);
- link_cflags = chaz_MakeBinary_get_link_flags(exe);
- chaz_CFlags_add_shared_lib(link_cflags, NULL, "cfish",
+
+ link_flags = chaz_MakeBinary_get_link_flags(exe);
+ chaz_CFlags_add_rpath(link_flags, "\"$$PWD\"");
+ chaz_CFlags_add_shared_lib(link_flags, NULL, "testcfish",
cfish_major_version);
- chaz_CFlags_add_rpath(link_cflags, "\"$$PWD\"");
+ chaz_CFlags_add_shared_lib(link_flags, NULL, "cfish",
+ cfish_major_version);
+
+ chaz_MakeBinary_add_prereq(exe, "$(TESTCFISH_SHARED_LIB)");
chaz_MakeBinary_add_prereq(exe, "$(CFISH_SHARED_LIB)");
+ chaz_MakeFile_add_rule(self->makefile, "$(TEST_CFISH_EXE_OBJS)",
+ self->autogen_target);
+
rule = chaz_MakeFile_add_rule(self->makefile, "test", "$(TEST_CFISH_EXE)");
chaz_MakeRule_add_command(rule, "$(TEST_CFISH_EXE)");
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/go/build.go
----------------------------------------------------------------------
diff --git a/runtime/go/build.go b/runtime/go/build.go
index c6eb9e3..46d70cc 100644
--- a/runtime/go/build.go
+++ b/runtime/go/build.go
@@ -109,7 +109,7 @@ func configure() {
if !current(charmonizerC, charmonizerEXE) {
runCommand("cc", "-o", charmonizerEXE, charmonizerC)
}
- if !current(charmonizerEXE, charmonyH) {
+ if !current(charmonizerEXE, charmonyH) || !current(charmonizerEXE, "Makefile") {
runCommand("./charmonizer", "--cc=cc", "--enable-c", "--host=go",
"--enable-makefile", "--disable-threads", "--", "-std=gnu99",
"-O2")
@@ -265,6 +265,7 @@ func writeConfigGO() {
"// #cgo CFLAGS: -I%s\n"+
"// #cgo CFLAGS: -I%s/autogen/include\n"+
"// #cgo LDFLAGS: -L%s\n"+
+ "// #cgo LDFLAGS: -ltestcfish\n"+
"// #cgo LDFLAGS: -lclownfish\n"+
"import \"C\"\n",
buildDir, buildDir, buildDir, buildDir)
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/perl/.gitignore
----------------------------------------------------------------------
diff --git a/runtime/perl/.gitignore b/runtime/perl/.gitignore
index 4e0ff0f..7c4733f 100644
--- a/runtime/perl/.gitignore
+++ b/runtime/perl/.gitignore
@@ -14,6 +14,8 @@
/charmony.h
/lib/Clownfish.c
/lib/Clownfish.xs
+/lib/Clownfish/Test.c
+/lib/Clownfish/Test.xs
/ppport.h
/typemap
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/perl/buildlib/Clownfish/Build.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/buildlib/Clownfish/Build.pm b/runtime/perl/buildlib/Clownfish/Build.pm
index 81b5fbf..0eef5c3 100644
--- a/runtime/perl/buildlib/Clownfish/Build.pm
+++ b/runtime/perl/buildlib/Clownfish/Build.pm
@@ -77,10 +77,16 @@ sub new {
modules => [
{
name => 'Clownfish',
- parcels => [ 'Clownfish', 'TestClownfish' ],
+ parcels => [ 'Clownfish' ],
make_target => 'core_objects',
c_source_dirs => [ $XS_SOURCE_DIR ],
},
+ {
+ name => 'Clownfish::Test',
+ parcels => [ 'TestClownfish' ],
+ make_target => 'test_objects',
+ xs_prereqs => [ 'Clownfish' ],
+ },
],
};
my $self = $class->SUPER::new( recursive_test_files => 1, %args );
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/perl/buildlib/Clownfish/Build/Binding.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/buildlib/Clownfish/Build/Binding.pm b/runtime/perl/buildlib/Clownfish/Build/Binding.pm
index 8da4d83..71b0ff8 100644
--- a/runtime/perl/buildlib/Clownfish/Build/Binding.pm
+++ b/runtime/perl/buildlib/Clownfish/Build/Binding.pm
@@ -67,7 +67,7 @@ END_XS_CODE
sub bind_test {
my $xs_code = <<'END_XS_CODE';
-MODULE = Clownfish PACKAGE = Clownfish::Test
+MODULE = Clownfish::Test PACKAGE = Clownfish::Test
SV*
create_test_suite()
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/perl/lib/Clownfish/Test.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/lib/Clownfish/Test.pm b/runtime/perl/lib/Clownfish/Test.pm
index e637cd3..55aeb94 100644
--- a/runtime/perl/lib/Clownfish/Test.pm
+++ b/runtime/perl/lib/Clownfish/Test.pm
@@ -18,6 +18,14 @@ use Clownfish;
our $VERSION = '0.005000';
$VERSION = eval $VERSION;
+sub dl_load_flags { 1 }
+
+BEGIN {
+ require DynaLoader;
+ our @ISA = qw( DynaLoader );
+ bootstrap Clownfish::Test '0.5.0';
+}
+
sub run_tests {
my $class_name = shift;
my $formatter = Clownfish::TestHarness::TestFormatterTAP->new();
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/perl/t/binding/019-obj.t
----------------------------------------------------------------------
diff --git a/runtime/perl/t/binding/019-obj.t b/runtime/perl/t/binding/019-obj.t
index 3d22c4e..c5eec3b 100644
--- a/runtime/perl/t/binding/019-obj.t
+++ b/runtime/perl/t/binding/019-obj.t
@@ -17,6 +17,7 @@ use strict;
use warnings;
use Test::More tests => 25;
+use Clownfish::Test;
package TestObj;
use base qw( Clownfish::Obj );
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/perl/t/binding/023-string.t
----------------------------------------------------------------------
diff --git a/runtime/perl/t/binding/023-string.t b/runtime/perl/t/binding/023-string.t
index 4f839c5..cae8476 100644
--- a/runtime/perl/t/binding/023-string.t
+++ b/runtime/perl/t/binding/023-string.t
@@ -53,6 +53,7 @@ is( $buf, $wanted, 'iter next' );
{
package MyStringCallbackTest;
+ use Clownfish::Test;
use base qw(Clownfish::Test::StringCallbackTest);
our $string_ref;
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/ef738c21/runtime/python/setup.py
----------------------------------------------------------------------
diff --git a/runtime/python/setup.py b/runtime/python/setup.py
index 717ce50..8860d3b 100644
--- a/runtime/python/setup.py
+++ b/runtime/python/setup.py
@@ -58,8 +58,10 @@ CHARMONIZER_C = os.path.join(COMMON_SOURCE_DIR, 'charmonizer.c')
CHARMONIZER_EXE_NAME = compiler.executable_filename('charmonizer')
CHARMONIZER_EXE_PATH = os.path.join(os.curdir, CHARMONIZER_EXE_NAME)
CHARMONY_H_PATH = 'charmony.h'
-LIBCLOWNFISH_NAME = 'libclownfish.a' # TODO portability
-LIBCLOWNFISH_PATH = os.path.abspath(os.path.join(os.curdir, LIBCLOWNFISH_NAME))
+CORELIB_NAME = 'libclownfish.a' # TODO portability
+CORELIB_PATH = os.path.abspath(os.path.join(os.curdir, CORELIB_NAME))
+TESTLIB_NAME = 'libtestcfish.a' # TODO portability
+TESTLIB_PATH = os.path.abspath(os.path.join(os.curdir, TESTLIB_NAME))
AUTOGEN_INCLUDE = os.path.join('autogen', 'include')
CFC_DIR = os.path.join(BASE_DIR, 'compiler', 'python')
CFC_BUILD_DIR = ext_build_dir(os.path.join(CFC_DIR))
@@ -198,7 +200,10 @@ clownfish_extension = Extension('clownfish._clownfish',
CFEXT_DIR,
os.curdir,
],
- extra_link_args = [LIBCLOWNFISH_PATH],
+ extra_link_args = [
+ CORELIB_PATH,
+ TESTLIB_PATH,
+ ],
sources = c_filepaths)
setup(name = 'clownfish',
[13/14] lucy-clownfish git commit: Fix Makefile paths for Perl CPAN
build
Posted by nw...@apache.org.
Fix Makefile paths for Perl CPAN build
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/a45abf04
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/a45abf04
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/a45abf04
Branch: refs/heads/master
Commit: a45abf04a63b7a9d0a2fc40af79216d8778d4d84
Parents: 3764180
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 8 13:57:47 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 8 14:37:20 2016 +0200
----------------------------------------------------------------------
runtime/common/charmonizer.c | 19 ++++++++++++++-----
runtime/common/charmonizer.main | 19 ++++++++++++++-----
2 files changed, 28 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a45abf04/runtime/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.c b/runtime/common/charmonizer.c
index 102970e..27753cc 100644
--- a/runtime/common/charmonizer.c
+++ b/runtime/common/charmonizer.c
@@ -8801,7 +8801,8 @@ S_link_flags(chaz_CLI *cli) {
static cfish_MakeFile*
cfish_MakeFile_new(chaz_CLI *cli) {
const char *dir_sep = chaz_OS_dir_sep();
-
+ char *cfcore_filename = chaz_Util_join(dir_sep, "cfcore", "Clownfish.cfp",
+ NULL);
cfish_MakeFile *self = malloc(sizeof(cfish_MakeFile));
self->makefile = chaz_MakeFile_new();
@@ -8810,10 +8811,17 @@ cfish_MakeFile_new(chaz_CLI *cli) {
self->cfh_var = NULL;
self->cli = cli;
- /* TODO: Detect base directory. */
- self->base_dir = "..";
- self->core_dir = chaz_Util_join(dir_sep, self->base_dir, "core", NULL);
- self->test_dir = chaz_Util_join(dir_sep, self->base_dir, "test", NULL);
+ if (chaz_Util_can_open_file(cfcore_filename)) {
+ self->base_dir = ".";
+ self->core_dir = chaz_Util_strdup("cfcore");
+ self->test_dir = chaz_Util_strdup("cftest");
+ }
+ else {
+ self->base_dir = "..";
+ self->core_dir = chaz_Util_join(dir_sep, "..", "core", NULL);
+ self->test_dir = chaz_Util_join(dir_sep, "..", "test", NULL);
+ }
+
self->autogen_src_dir = chaz_Util_join(dir_sep, "autogen", "source", NULL);
self->autogen_inc_dir
= chaz_Util_join(dir_sep, "autogen", "include", NULL);
@@ -8835,6 +8843,7 @@ cfish_MakeFile_new(chaz_CLI *cli) {
self->host_src_dir = NULL;
}
+ free(cfcore_filename);
return self;
}
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a45abf04/runtime/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.main b/runtime/common/charmonizer.main
index fc68fd4..681d263 100644
--- a/runtime/common/charmonizer.main
+++ b/runtime/common/charmonizer.main
@@ -253,7 +253,8 @@ S_link_flags(chaz_CLI *cli) {
static cfish_MakeFile*
cfish_MakeFile_new(chaz_CLI *cli) {
const char *dir_sep = chaz_OS_dir_sep();
-
+ char *cfcore_filename = chaz_Util_join(dir_sep, "cfcore", "Clownfish.cfp",
+ NULL);
cfish_MakeFile *self = malloc(sizeof(cfish_MakeFile));
self->makefile = chaz_MakeFile_new();
@@ -262,10 +263,17 @@ cfish_MakeFile_new(chaz_CLI *cli) {
self->cfh_var = NULL;
self->cli = cli;
- /* TODO: Detect base directory. */
- self->base_dir = "..";
- self->core_dir = chaz_Util_join(dir_sep, self->base_dir, "core", NULL);
- self->test_dir = chaz_Util_join(dir_sep, self->base_dir, "test", NULL);
+ if (chaz_Util_can_open_file(cfcore_filename)) {
+ self->base_dir = ".";
+ self->core_dir = chaz_Util_strdup("cfcore");
+ self->test_dir = chaz_Util_strdup("cftest");
+ }
+ else {
+ self->base_dir = "..";
+ self->core_dir = chaz_Util_join(dir_sep, "..", "core", NULL);
+ self->test_dir = chaz_Util_join(dir_sep, "..", "test", NULL);
+ }
+
self->autogen_src_dir = chaz_Util_join(dir_sep, "autogen", "source", NULL);
self->autogen_inc_dir
= chaz_Util_join(dir_sep, "autogen", "include", NULL);
@@ -287,6 +295,7 @@ cfish_MakeFile_new(chaz_CLI *cli) {
self->host_src_dir = NULL;
}
+ free(cfcore_filename);
return self;
}
[09/14] lucy-clownfish git commit: Move tests to separate directory
Posted by nw...@apache.org.
Move tests to separate directory
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/8ba4e619
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/8ba4e619
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/8ba4e619
Branch: refs/heads/master
Commit: 8ba4e61987f00db2624818c4fa1a6f9c1b4f79b8
Parents: 5bda4da
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 8 13:57:13 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 8 14:25:36 2016 +0200
----------------------------------------------------------------------
runtime/common/charmonizer.c | 7 +
runtime/common/charmonizer.main | 7 +
runtime/core/Clownfish/Test.c | 70 --
runtime/core/Clownfish/Test.cfh | 26 -
runtime/core/Clownfish/Test/TestBlob.c | 147 ----
runtime/core/Clownfish/Test/TestBlob.cfh | 28 -
runtime/core/Clownfish/Test/TestBoolean.c | 99 ---
runtime/core/Clownfish/Test/TestBoolean.cfh | 29 -
runtime/core/Clownfish/Test/TestByteBuf.c | 218 -----
runtime/core/Clownfish/Test/TestByteBuf.cfh | 29 -
runtime/core/Clownfish/Test/TestCharBuf.c | 394 ---------
runtime/core/Clownfish/Test/TestCharBuf.cfh | 29 -
runtime/core/Clownfish/Test/TestClass.c | 158 ----
runtime/core/Clownfish/Test/TestClass.cfh | 28 -
runtime/core/Clownfish/Test/TestErr.c | 193 -----
runtime/core/Clownfish/Test/TestErr.cfh | 28 -
runtime/core/Clownfish/Test/TestHash.c | 325 -------
runtime/core/Clownfish/Test/TestHash.cfh | 29 -
runtime/core/Clownfish/Test/TestHashIterator.c | 253 ------
.../core/Clownfish/Test/TestHashIterator.cfh | 29 -
runtime/core/Clownfish/Test/TestHost.c | 125 ---
runtime/core/Clownfish/Test/TestHost.cfh | 81 --
.../core/Clownfish/Test/TestLockFreeRegistry.c | 168 ----
.../Clownfish/Test/TestLockFreeRegistry.cfh | 29 -
runtime/core/Clownfish/Test/TestMethod.c | 91 --
runtime/core/Clownfish/Test/TestMethod.cfh | 28 -
runtime/core/Clownfish/Test/TestNum.c | 278 ------
runtime/core/Clownfish/Test/TestNum.cfh | 29 -
runtime/core/Clownfish/Test/TestObj.c | 152 ----
runtime/core/Clownfish/Test/TestObj.cfh | 28 -
runtime/core/Clownfish/Test/TestPtrHash.c | 108 ---
runtime/core/Clownfish/Test/TestPtrHash.cfh | 29 -
runtime/core/Clownfish/Test/TestString.c | 848 -------------------
runtime/core/Clownfish/Test/TestString.cfh | 36 -
runtime/core/Clownfish/Test/TestVector.c | 572 -------------
runtime/core/Clownfish/Test/TestVector.cfh | 29 -
runtime/core/Clownfish/Test/Util/TestAtomic.c | 65 --
runtime/core/Clownfish/Test/Util/TestAtomic.cfh | 29 -
runtime/core/Clownfish/Test/Util/TestMemory.c | 119 ---
runtime/core/Clownfish/Test/Util/TestMemory.cfh | 29 -
.../core/Clownfish/Test/Util/TestStringHelper.c | 373 --------
.../Clownfish/Test/Util/TestStringHelper.cfh | 29 -
runtime/core/TestClownfish.c | 22 -
runtime/core/TestClownfish.cfp | 8 -
runtime/go/build.go | 1 +
runtime/perl/buildlib/Clownfish/Build.pm | 6 +-
runtime/python/setup.py | 2 +
runtime/test/Clownfish/Test.c | 70 ++
runtime/test/Clownfish/Test.cfh | 26 +
runtime/test/Clownfish/Test/TestBlob.c | 147 ++++
runtime/test/Clownfish/Test/TestBlob.cfh | 28 +
runtime/test/Clownfish/Test/TestBoolean.c | 99 +++
runtime/test/Clownfish/Test/TestBoolean.cfh | 29 +
runtime/test/Clownfish/Test/TestByteBuf.c | 218 +++++
runtime/test/Clownfish/Test/TestByteBuf.cfh | 29 +
runtime/test/Clownfish/Test/TestCharBuf.c | 394 +++++++++
runtime/test/Clownfish/Test/TestCharBuf.cfh | 29 +
runtime/test/Clownfish/Test/TestClass.c | 158 ++++
runtime/test/Clownfish/Test/TestClass.cfh | 28 +
runtime/test/Clownfish/Test/TestErr.c | 193 +++++
runtime/test/Clownfish/Test/TestErr.cfh | 28 +
runtime/test/Clownfish/Test/TestHash.c | 325 +++++++
runtime/test/Clownfish/Test/TestHash.cfh | 29 +
runtime/test/Clownfish/Test/TestHashIterator.c | 253 ++++++
.../test/Clownfish/Test/TestHashIterator.cfh | 29 +
runtime/test/Clownfish/Test/TestHost.c | 125 +++
runtime/test/Clownfish/Test/TestHost.cfh | 81 ++
.../test/Clownfish/Test/TestLockFreeRegistry.c | 168 ++++
.../Clownfish/Test/TestLockFreeRegistry.cfh | 29 +
runtime/test/Clownfish/Test/TestMethod.c | 91 ++
runtime/test/Clownfish/Test/TestMethod.cfh | 28 +
runtime/test/Clownfish/Test/TestNum.c | 278 ++++++
runtime/test/Clownfish/Test/TestNum.cfh | 29 +
runtime/test/Clownfish/Test/TestObj.c | 152 ++++
runtime/test/Clownfish/Test/TestObj.cfh | 28 +
runtime/test/Clownfish/Test/TestPtrHash.c | 108 +++
runtime/test/Clownfish/Test/TestPtrHash.cfh | 29 +
runtime/test/Clownfish/Test/TestString.c | 848 +++++++++++++++++++
runtime/test/Clownfish/Test/TestString.cfh | 36 +
runtime/test/Clownfish/Test/TestVector.c | 572 +++++++++++++
runtime/test/Clownfish/Test/TestVector.cfh | 29 +
runtime/test/Clownfish/Test/Util/TestAtomic.c | 65 ++
runtime/test/Clownfish/Test/Util/TestAtomic.cfh | 29 +
runtime/test/Clownfish/Test/Util/TestMemory.c | 119 +++
runtime/test/Clownfish/Test/Util/TestMemory.cfh | 29 +
.../test/Clownfish/Test/Util/TestStringHelper.c | 373 ++++++++
.../Clownfish/Test/Util/TestStringHelper.cfh | 29 +
runtime/test/TestClownfish.c | 22 +
runtime/test/TestClownfish.cfp | 8 +
89 files changed, 5439 insertions(+), 5418 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.c b/runtime/common/charmonizer.c
index 7448e25..af37cfd 100644
--- a/runtime/common/charmonizer.c
+++ b/runtime/common/charmonizer.c
@@ -8597,6 +8597,7 @@ typedef struct cfish_MakeFile {
const char *base_dir;
const char *host_src_dir;
char *core_dir;
+ char *test_dir;
char *autogen_src_dir;
char *autogen_inc_dir;
char *autogen_target;
@@ -8807,8 +8808,10 @@ cfish_MakeFile_new(chaz_CLI *cli) {
self->cfh_var = NULL;
self->cli = cli;
+ /* TODO: Detect base directory. */
self->base_dir = "..";
self->core_dir = chaz_Util_join(dir_sep, self->base_dir, "core", NULL);
+ self->test_dir = chaz_Util_join(dir_sep, self->base_dir, "test", NULL);
self->autogen_src_dir = chaz_Util_join(dir_sep, "autogen", "source", NULL);
self->autogen_inc_dir
= chaz_Util_join(dir_sep, "autogen", "include", NULL);
@@ -8838,6 +8841,7 @@ cfish_MakeFile_destroy(cfish_MakeFile *self) {
chaz_MakeFile_destroy(self->makefile);
free(self->core_dir);
+ free(self->test_dir);
free(self->autogen_inc_dir);
free(self->autogen_src_dir);
free(self->autogen_target);
@@ -8924,6 +8928,7 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
chaz_MakeBinary_add_src_dir(self->binary, self->host_src_dir);
}
chaz_MakeBinary_add_src_dir(self->binary, self->core_dir);
+ chaz_MakeBinary_add_src_dir(self->binary, self->test_dir);
compile_flags = chaz_MakeBinary_get_compile_flags(self->binary);
chaz_CFlags_add_define(compile_flags, "CFP_CFISH", NULL);
@@ -8988,10 +8993,12 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
self->cfh_var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_HEADERS",
NULL);
chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, self);
+ chaz_Make_list_files(self->test_dir, "cfh", S_cfh_file_callback, self);
rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target, cfc_exe);
chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
cfc_command = chaz_Util_join("", cfc_exe, " --source=", self->core_dir,
+ " --source=", self->test_dir,
" --dest=autogen --header=cfc_header", NULL);
chaz_MakeRule_add_command(rule, cfc_command);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.main b/runtime/common/charmonizer.main
index e777c52..7ceb2dd 100644
--- a/runtime/common/charmonizer.main
+++ b/runtime/common/charmonizer.main
@@ -49,6 +49,7 @@ typedef struct cfish_MakeFile {
const char *base_dir;
const char *host_src_dir;
char *core_dir;
+ char *test_dir;
char *autogen_src_dir;
char *autogen_inc_dir;
char *autogen_target;
@@ -259,8 +260,10 @@ cfish_MakeFile_new(chaz_CLI *cli) {
self->cfh_var = NULL;
self->cli = cli;
+ /* TODO: Detect base directory. */
self->base_dir = "..";
self->core_dir = chaz_Util_join(dir_sep, self->base_dir, "core", NULL);
+ self->test_dir = chaz_Util_join(dir_sep, self->base_dir, "test", NULL);
self->autogen_src_dir = chaz_Util_join(dir_sep, "autogen", "source", NULL);
self->autogen_inc_dir
= chaz_Util_join(dir_sep, "autogen", "include", NULL);
@@ -290,6 +293,7 @@ cfish_MakeFile_destroy(cfish_MakeFile *self) {
chaz_MakeFile_destroy(self->makefile);
free(self->core_dir);
+ free(self->test_dir);
free(self->autogen_inc_dir);
free(self->autogen_src_dir);
free(self->autogen_target);
@@ -376,6 +380,7 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
chaz_MakeBinary_add_src_dir(self->binary, self->host_src_dir);
}
chaz_MakeBinary_add_src_dir(self->binary, self->core_dir);
+ chaz_MakeBinary_add_src_dir(self->binary, self->test_dir);
compile_flags = chaz_MakeBinary_get_compile_flags(self->binary);
chaz_CFlags_add_define(compile_flags, "CFP_CFISH", NULL);
@@ -440,10 +445,12 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
self->cfh_var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_HEADERS",
NULL);
chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, self);
+ chaz_Make_list_files(self->test_dir, "cfh", S_cfh_file_callback, self);
rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target, cfc_exe);
chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
cfc_command = chaz_Util_join("", cfc_exe, " --source=", self->core_dir,
+ " --source=", self->test_dir,
" --dest=autogen --header=cfc_header", NULL);
chaz_MakeRule_add_command(rule, cfc_command);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test.c b/runtime/core/Clownfish/Test.c
deleted file mode 100644
index 4ae6163..0000000
--- a/runtime/core/Clownfish/Test.c
+++ /dev/null
@@ -1,70 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test.h"
-
-#include "Clownfish/TestHarness/TestBatch.h"
-#include "Clownfish/TestHarness/TestSuite.h"
-
-#include "Clownfish/Test/TestBlob.h"
-#include "Clownfish/Test/TestBoolean.h"
-#include "Clownfish/Test/TestByteBuf.h"
-#include "Clownfish/Test/TestString.h"
-#include "Clownfish/Test/TestCharBuf.h"
-#include "Clownfish/Test/TestClass.h"
-#include "Clownfish/Test/TestErr.h"
-#include "Clownfish/Test/TestHash.h"
-#include "Clownfish/Test/TestHashIterator.h"
-#include "Clownfish/Test/TestLockFreeRegistry.h"
-#include "Clownfish/Test/TestMethod.h"
-#include "Clownfish/Test/TestNum.h"
-#include "Clownfish/Test/TestObj.h"
-#include "Clownfish/Test/TestPtrHash.h"
-#include "Clownfish/Test/TestVector.h"
-#include "Clownfish/Test/Util/TestAtomic.h"
-#include "Clownfish/Test/Util/TestMemory.h"
-#include "Clownfish/Test/Util/TestStringHelper.h"
-
-TestSuite*
-Test_create_test_suite() {
- TestSuite *suite = TestSuite_new();
-
- TestSuite_Add_Batch(suite, (TestBatch*)TestClass_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestMethod_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestVector_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestHash_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestHashIterator_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestObj_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestErr_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestBlob_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestBB_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestStr_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestCB_new());
- TestSuite_Add_Batch(suite, (TestBatch*)TestBoolean_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());
- TestSuite_Add_Batch(suite, (TestBatch*)TestPtrHash_new());
-
- return suite;
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test.cfh b/runtime/core/Clownfish/Test.cfh
deleted file mode 100644
index 68dc8bc..0000000
--- a/runtime/core/Clownfish/Test.cfh
+++ /dev/null
@@ -1,26 +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 TestClownfish;
-
-/** Clownfish test suite.
- */
-inert class Clownfish::Test {
- inert incremented TestSuite*
- create_test_suite();
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestBlob.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestBlob.c b/runtime/core/Clownfish/Test/TestBlob.c
deleted file mode 100644
index 5776f47..0000000
--- a/runtime/core/Clownfish/Test/TestBlob.c
+++ /dev/null
@@ -1,147 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestBlob.h"
-
-#include "Clownfish/Blob.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Class.h"
-#include "Clownfish/Util/Memory.h"
-
-#include <string.h>
-
-TestBlob*
-TestBlob_new() {
- return (TestBlob*)Class_Make_Obj(TESTBLOB);
-}
-
-static void
-test_new_steal(TestBatchRunner *runner) {
- size_t size = 4;
- char *buf = (char*)MALLOCATE(size);
- memset(buf, 'x', size);
- Blob *blob = Blob_new_steal(buf, size);
- TEST_TRUE(runner, Blob_Get_Buf(blob) == buf, "new_steal steals buf");
- TEST_TRUE(runner, Blob_Equals_Bytes(blob, "xxxx", 4),
- "new_steal doesn't change buf");
- DECREF(blob);
-}
-
-static void
-test_new_wrap(TestBatchRunner *runner) {
- static const char buf[] = "xxxx";
- Blob *blob = Blob_new_wrap(buf, 4);
- TEST_TRUE(runner, Blob_Get_Buf(blob) == buf, "new_wrap wraps buf");
- TEST_TRUE(runner, Blob_Equals_Bytes(blob, "xxxx", 4),
- "new_wrap doesn't change buf");
- DECREF(blob);
-}
-
-static void
-test_Equals(TestBatchRunner *runner) {
- Blob *blob = Blob_new("foo", 4); // Include terminating NULL.
-
- {
- Blob *other = Blob_new("foo", 4);
- TEST_TRUE(runner, Blob_Equals(blob, (Obj*)other), "Equals");
- DECREF(other);
- }
-
- {
- Blob *other = Blob_new("foo", 3);
- TEST_FALSE(runner, Blob_Equals(blob, (Obj*)other),
- "Different size spoils Equals");
- DECREF(other);
- }
-
- {
- Blob *other = Blob_new("bar", 4);
- TEST_UINT_EQ(runner, Blob_Get_Size(blob), Blob_Get_Size(other),
- "same length");
- TEST_FALSE(runner, Blob_Equals(blob, (Obj*)other),
- "Different content spoils Equals");
- DECREF(other);
- }
-
- TEST_FALSE(runner, Blob_Equals(blob, (Obj*)BLOB),
- "Different type spoils Equals");
-
- TEST_TRUE(runner, Blob_Equals_Bytes(blob, "foo", 4), "Equals_Bytes");
- TEST_FALSE(runner, Blob_Equals_Bytes(blob, "foo", 3),
- "Equals_Bytes spoiled by different size");
- TEST_FALSE(runner, Blob_Equals_Bytes(blob, "bar", 4),
- "Equals_Bytes spoiled by different content");
-
- DECREF(blob);
-}
-
-static void
-test_Clone(TestBatchRunner *runner) {
- Blob *blob = Blob_new("foo", 3);
- Blob *twin = Blob_Clone(blob);
- TEST_TRUE(runner, Blob_Equals(blob, (Obj*)twin), "Clone");
- DECREF(blob);
- DECREF(twin);
-}
-
-static void
-test_Compare_To(TestBatchRunner *runner) {
- {
- Blob *a = Blob_new("foo", 4);
- Blob *b = Blob_new("foo", 4);
- TEST_INT_EQ(runner, Blob_Compare_To(a, (Obj*)b), 0,
- "Compare_To returns 0 for equal Blobs");
- DECREF(a);
- DECREF(b);
- }
-
- {
- Blob *a = Blob_new("foo", 3);
- Blob *b = Blob_new("foo\0b", 5);
- TEST_TRUE(runner, Blob_Compare_To(a, (Obj*)b) < 0,
- "shorter Blob sorts first");
- TEST_TRUE(runner, Blob_Compare_To(b, (Obj*)a) > 0,
- "longer Blob sorts last");
- DECREF(a);
- DECREF(b);
- }
-
- {
- Blob *a = Blob_new("foo\0a", 5);
- Blob *b = Blob_new("foo\0b", 5);
- TEST_TRUE(runner, Blob_Compare_To(a, (Obj*)b) < 0,
- "NULL doesn't interfere with Compare_To");
- DECREF(a);
- DECREF(b);
- }
-}
-
-void
-TestBlob_Run_IMP(TestBlob *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 17);
- test_new_steal(runner);
- test_new_wrap(runner);
- test_Equals(runner);
- test_Clone(runner);
- test_Compare_To(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestBlob.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestBlob.cfh b/runtime/core/Clownfish/Test/TestBlob.cfh
deleted file mode 100644
index 4d3d4b6..0000000
--- a/runtime/core/Clownfish/Test/TestBlob.cfh
+++ /dev/null
@@ -1,28 +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 TestClownfish;
-
-class Clownfish::Test::TestBlob inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestBlob*
- new();
-
- void
- Run(TestBlob *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestBoolean.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestBoolean.c b/runtime/core/Clownfish/Test/TestBoolean.c
deleted file mode 100644
index 8835fe1..0000000
--- a/runtime/core/Clownfish/Test/TestBoolean.c
+++ /dev/null
@@ -1,99 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestBoolean.h"
-
-#include "Clownfish/String.h"
-#include "Clownfish/Boolean.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Class.h"
-
-TestBoolean*
-TestBoolean_new() {
- return (TestBoolean*)Class_Make_Obj(TESTBOOLEAN);
-}
-
-static void
-test_singleton(TestBatchRunner *runner) {
- TEST_TRUE(runner, Bool_singleton(true) == CFISH_TRUE,
- "Bool_singleton true");
- TEST_TRUE(runner, Bool_singleton(false) == CFISH_FALSE,
- "Bool_singleton false");
-}
-
-static void
-test_To_String(TestBatchRunner *runner) {
- String *true_string = Bool_To_String(CFISH_TRUE);
- String *false_string = Bool_To_String(CFISH_FALSE);
-
- TEST_TRUE(runner, Str_Equals_Utf8(true_string, "true", 4),
- "Bool_To_String [true]");
- TEST_TRUE(runner, Str_Equals_Utf8(false_string, "false", 5),
- "Bool_To_String [false]");
-
- DECREF(false_string);
- DECREF(true_string);
-}
-
-static void
-test_accessors(TestBatchRunner *runner) {
- TEST_INT_EQ(runner, Bool_Get_Value(CFISH_TRUE), true,
- "Bool_Get_Value [true]");
- TEST_INT_EQ(runner, Bool_Get_Value(CFISH_FALSE), false,
- "Bool_Get_Value [false]");
-}
-
-static void
-test_Equals_and_Compare_To(TestBatchRunner *runner) {
- TEST_TRUE(runner, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_TRUE),
- "CFISH_TRUE Equals itself");
- TEST_TRUE(runner, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_FALSE),
- "CFISH_FALSE Equals itself");
- TEST_FALSE(runner, Bool_Equals(CFISH_FALSE, (Obj*)CFISH_TRUE),
- "CFISH_FALSE not Equals CFISH_TRUE ");
- TEST_FALSE(runner, Bool_Equals(CFISH_TRUE, (Obj*)CFISH_FALSE),
- "CFISH_TRUE not Equals CFISH_FALSE ");
- TEST_FALSE(runner, Bool_Equals(CFISH_TRUE, (Obj*)STRING),
- "CFISH_TRUE not Equals random other object ");
-}
-
-static void
-test_Clone(TestBatchRunner *runner) {
- TEST_TRUE(runner, Bool_Equals(CFISH_TRUE, (Obj*)Bool_Clone(CFISH_TRUE)),
- "Boolean Clone");
-}
-
-void
-TestBoolean_Run_IMP(TestBoolean *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 12);
-
- // Destroying the singletons should have no effect.
- Bool_Destroy(CFISH_TRUE);
- Bool_Destroy(CFISH_FALSE);
-
- test_singleton(runner);
- test_To_String(runner);
- test_accessors(runner);
- test_Equals_and_Compare_To(runner);
- test_Clone(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestBoolean.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestBoolean.cfh b/runtime/core/Clownfish/Test/TestBoolean.cfh
deleted file mode 100644
index 43702db..0000000
--- a/runtime/core/Clownfish/Test/TestBoolean.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::TestBoolean
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestBoolean*
- new();
-
- void
- Run(TestBoolean *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestByteBuf.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestByteBuf.c b/runtime/core/Clownfish/Test/TestByteBuf.c
deleted file mode 100644
index 7f8fc50..0000000
--- a/runtime/core/Clownfish/Test/TestByteBuf.c
+++ /dev/null
@@ -1,218 +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>
-
-#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/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Blob.h"
-#include "Clownfish/Class.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/String.h"
-#include "Clownfish/Util/Memory.h"
-
-#include <string.h>
-
-TestByteBuf*
-TestBB_new() {
- return (TestByteBuf*)Class_Make_Obj(TESTBYTEBUF);
-}
-
-static void
-test_new_steal_bytes(TestBatchRunner *runner) {
- char *buf = (char*)MALLOCATE(10);
- memset(buf, 'x', 10);
- ByteBuf *bb = BB_new_steal_bytes(buf, 5, 10);
- TEST_TRUE(runner, BB_Get_Buf(bb) == buf, "new_steal_bytes steals buffer");
- TEST_TRUE(runner, BB_Equals_Bytes(bb, "xxxxx", 5),
- "new_steal_bytes sets correct size");
- BB_Set_Size(bb, 10);
- TEST_TRUE(runner, BB_Equals_Bytes(bb, "xxxxxxxxxx", 10),
- "new_steal_bytes sets correct capacity");
- DECREF(bb);
-}
-
-static void
-test_Equals(TestBatchRunner *runner) {
- ByteBuf *bb = BB_new_bytes("foo", 4); // Include terminating NULL.
-
- TEST_TRUE(runner, BB_Equals(bb, (Obj*)bb), "Equals self");
- TEST_FALSE(runner, BB_Equals(bb, (Obj*)BYTEBUF),
- "Equals spoiled by different type");
-
- {
- ByteBuf *other = BB_new_bytes("foo", 4);
- TEST_TRUE(runner, BB_Equals(bb, (Obj*)other), "Equals");
- DECREF(other);
- }
-
- TEST_TRUE(runner, BB_Equals_Bytes(bb, "foo", 4), "Equals_Bytes");
- TEST_FALSE(runner, BB_Equals_Bytes(bb, "foo", 3),
- "Equals_Bytes spoiled by different size");
- TEST_FALSE(runner, BB_Equals_Bytes(bb, "bar", 4),
- "Equals_Bytes spoiled by different content");
-
- {
- ByteBuf *other = BB_new_bytes("foo", 3);
- TEST_FALSE(runner, BB_Equals(bb, (Obj*)other),
- "Different size spoils Equals");
- DECREF(other);
- }
-
- {
- ByteBuf *other = BB_new_bytes("bar", 4);
- TEST_UINT_EQ(runner, BB_Get_Size(bb), BB_Get_Size(other),
- "same length");
- TEST_FALSE(runner, BB_Equals(bb, (Obj*)other),
- "Different content spoils Equals");
- DECREF(other);
- }
-
- DECREF(bb);
-}
-
-static void
-test_Grow(TestBatchRunner *runner) {
- ByteBuf *bb = BB_new(1);
- TEST_UINT_EQ(runner, BB_Get_Capacity(bb), 8,
- "Allocate in 8-byte increments");
- BB_Grow(bb, 9);
- TEST_UINT_EQ(runner, BB_Get_Capacity(bb), 16,
- "Grow in 8-byte increments");
- BB_Grow(bb, 16);
- TEST_UINT_EQ(runner, BB_Get_Capacity(bb), 16,
- "Grow to same capacity has no effect");
- DECREF(bb);
-}
-
-static void
-test_Clone(TestBatchRunner *runner) {
- ByteBuf *bb = BB_new_bytes("foo", 3);
- ByteBuf *twin = BB_Clone(bb);
- TEST_TRUE(runner, BB_Equals(bb, (Obj*)twin), "Clone");
- DECREF(bb);
- DECREF(twin);
-}
-
-static void
-test_Compare_To(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(runner, BB_Compare_To(a, (Obj*)b), 0,
- "Compare_To returns 0 for equal ByteBufs");
-
- BB_Set_Size(a, 3);
- TEST_TRUE(runner, BB_Compare_To(a, (Obj*)b) < 0,
- "shorter ByteBuf sorts first");
- TEST_TRUE(runner, BB_Compare_To(b, (Obj*)a) > 0,
- "longer ByteBuf sorts last");
-
- BB_Set_Size(a, 5);
- BB_Set_Size(b, 5);
- TEST_TRUE(runner, BB_Compare_To(a, (Obj*)b) < 0,
- "NULL doesn't interfere with Compare_To");
-
- DECREF(a);
- DECREF(b);
-}
-
-static void
-test_Cat(TestBatchRunner *runner) {
- ByteBuf *bb = BB_new_bytes("foo", 3);
-
- {
- Blob *blob = Blob_new("bar", 3);
- BB_Cat(bb, blob);
- TEST_TRUE(runner, BB_Equals_Bytes(bb, "foobar", 6), "Cat");
- DECREF(blob);
- }
-
- BB_Cat_Bytes(bb, "baz", 3);
- TEST_TRUE(runner, BB_Equals_Bytes(bb, "foobarbaz", 9), "Cat_Bytes");
-
- DECREF(bb);
-}
-
-static void
-test_Utf8_To_String(TestBatchRunner *runner) {
- ByteBuf *bb = BB_new_bytes("foo", 3);
-
- {
- String *string = BB_Utf8_To_String(bb);
- TEST_TRUE(runner, Str_Equals_Utf8(string, "foo", 3), "Utf8_To_String");
- DECREF(string);
- }
-
- {
- String *string = BB_Trusted_Utf8_To_String(bb);
- TEST_TRUE(runner, Str_Equals_Utf8(string, "foo", 3),
- "Trusted_Utf8_To_String");
- DECREF(string);
- }
-
- DECREF(bb);
-}
-
-static void
-S_set_wrong_size(void *context) {
- ByteBuf *bb = (ByteBuf*)context;
- BB_Set_Size(bb, BB_Get_Capacity(bb) + 1);
-}
-
-static void
-test_Set_Size(TestBatchRunner *runner) {
- ByteBuf *bb = BB_new(10);
- Err *error = Err_trap(S_set_wrong_size, bb);
- TEST_TRUE(runner, error != NULL, "Setting size beyond capacity throws");
- DECREF(error);
- DECREF(bb);
-}
-
-static void
-test_Yield_Blob(TestBatchRunner *runner) {
- ByteBuf *bb = BB_new_bytes("alpha", 5);
- Blob *blob = BB_Yield_Blob(bb);
- TEST_TRUE(runner, Blob_Equals_Bytes(blob, "alpha", 5), "Yield_Blob");
- TEST_UINT_EQ(runner, BB_Get_Size(bb), 0, "Yield_Blob clears buf");
- DECREF(blob);
- DECREF(bb);
-}
-
-void
-TestBB_Run_IMP(TestByteBuf *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 27);
- test_new_steal_bytes(runner);
- test_Equals(runner);
- test_Grow(runner);
- test_Clone(runner);
- test_Compare_To(runner);
- test_Cat(runner);
- test_Utf8_To_String(runner);
- test_Set_Size(runner);
- test_Yield_Blob(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestByteBuf.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestByteBuf.cfh b/runtime/core/Clownfish/Test/TestByteBuf.cfh
deleted file mode 100644
index d27e715..0000000
--- a/runtime/core/Clownfish/Test/TestByteBuf.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::TestByteBuf nickname TestBB
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestByteBuf*
- new();
-
- void
- Run(TestByteBuf *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestCharBuf.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestCharBuf.c b/runtime/core/Clownfish/Test/TestCharBuf.c
deleted file mode 100644
index 4329987..0000000
--- a/runtime/core/Clownfish/Test/TestCharBuf.c
+++ /dev/null
@@ -1,394 +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 <stdio.h>
-
-#define CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-#define C_CFISH_CHARBUF
-
-#include "charmony.h"
-
-#include "Clownfish/Test/TestCharBuf.h"
-
-#include "Clownfish/CharBuf.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Num.h"
-#include "Clownfish/String.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Class.h"
-
-static char smiley[] = { (char)0xE2, (char)0x98, (char)0xBA, 0 };
-static uint32_t smiley_len = 3;
-
-TestCharBuf*
-TestCB_new() {
- return (TestCharBuf*)Class_Make_Obj(TESTCHARBUF);
-}
-
-static CharBuf*
-S_get_cb(const char *string) {
- CharBuf *cb = CB_new(0);
- CB_Cat_Utf8(cb, string, strlen(string));
- return cb;
-}
-
-static String*
-S_get_str(const char *string) {
- return Str_new_from_utf8(string, strlen(string));
-}
-
-static bool
-S_cb_equals(CharBuf *cb, String *other) {
- String *string = CB_To_String(cb);
- bool retval = Str_Equals(string, (Obj*)other);
- DECREF(string);
- return retval;
-}
-
-static void
-S_cat_invalid_utf8(void *context) {
- CharBuf *cb = (CharBuf*)context;
- CB_Cat_Utf8(cb, "\xF0" "a", 2);
-}
-
-static void
-test_Cat(TestBatchRunner *runner) {
- String *wanted = Str_newf("a%s", smiley);
- CharBuf *got = S_get_cb("");
-
- CB_Cat(got, wanted);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat");
- DECREF(got);
-
- got = S_get_cb("a");
- CB_Cat_Char(got, 0x263A);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat_Char");
- DECREF(got);
-
- got = S_get_cb("a");
- CB_Cat_Utf8(got, smiley, smiley_len);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat_Utf8");
- DECREF(got);
-
- got = S_get_cb("a");
- Err *error = Err_trap(S_cat_invalid_utf8, got);
- TEST_TRUE(runner, error != NULL, "Cat_Utf8 throws with invalid UTF-8");
- DECREF(error);
- DECREF(got);
-
- got = S_get_cb("a");
- CB_Cat_Trusted_Utf8(got, smiley, smiley_len);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat_Trusted_Utf8");
- DECREF(got);
-
- DECREF(wanted);
-}
-
-static void
-test_Clone(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo");
- CharBuf *wanted_cb = S_get_cb("foo");
- CharBuf *got = CB_Clone(wanted_cb);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "Clone");
- DECREF(got);
- DECREF(wanted);
- DECREF(wanted_cb);
-}
-
-static void
-test_vcatf_percent(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo % bar");
- CharBuf *got = S_get_cb("foo");
- CB_catf(got, " %% bar");
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%%%");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_s(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo bar bizzle baz");
- CharBuf *got = S_get_cb("foo ");
- CB_catf(got, "bar %s baz", "bizzle");
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%s");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-S_catf_s_invalid_utf8(void *context) {
- CharBuf *buf = (CharBuf*)context;
- CB_catf(buf, "bar %s baz", "\x82" "abcd");
-}
-
-static void
-test_vcatf_s_invalid_utf8(TestBatchRunner *runner) {
- CharBuf *buf = S_get_cb("foo ");
- Err *error = Err_trap(S_catf_s_invalid_utf8, buf);
- TEST_TRUE(runner, error != NULL, "%%s with invalid UTF-8");
- DECREF(error);
- DECREF(buf);
-}
-
-static void
-test_vcatf_null_string(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo bar [NULL] baz");
- CharBuf *got = S_get_cb("foo ");
- CB_catf(got, "bar %s baz", NULL);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%s NULL");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_str(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo bar ZEKE baz");
- String *catworthy = S_get_str("ZEKE");
- CharBuf *got = S_get_cb("foo ");
- CB_catf(got, "bar %o baz", catworthy);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%o CharBuf");
- DECREF(catworthy);
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_obj(TestBatchRunner *runner) {
- String *wanted = S_get_str("ooga 20 booga");
- Integer *i64 = Int_new(20);
- CharBuf *got = S_get_cb("ooga");
- CB_catf(got, " %o booga", i64);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%o Obj");
- DECREF(i64);
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_null_obj(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo bar [NULL] baz");
- CharBuf *got = S_get_cb("foo ");
- CB_catf(got, "bar %o baz", NULL);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%o NULL");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_i8(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo bar -3 baz");
- int8_t num = -3;
- CharBuf *got = S_get_cb("foo ");
- CB_catf(got, "bar %i8 baz", num);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%i8");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_i32(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo bar -100000 baz");
- int32_t num = -100000;
- CharBuf *got = S_get_cb("foo ");
- CB_catf(got, "bar %i32 baz", num);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%i32");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_i64(TestBatchRunner *runner) {
- String *wanted = S_get_str("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(runner, S_cb_equals(got, wanted), "%%i64");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_u8(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo bar 3 baz");
- uint8_t num = 3;
- CharBuf *got = S_get_cb("foo ");
- CB_catf(got, "bar %u8 baz", num);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%u8");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_u32(TestBatchRunner *runner) {
- String *wanted = S_get_str("foo bar 100000 baz");
- uint32_t num = 100000;
- CharBuf *got = S_get_cb("foo ");
- CB_catf(got, "bar %u32 baz", num);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%u32");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_u64(TestBatchRunner *runner) {
- String *wanted = S_get_str("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(runner, S_cb_equals(got, wanted), "%%u64");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_f64(TestBatchRunner *runner) {
- String *wanted;
- char buf[64];
- float num = 1.3f;
- CharBuf *got = S_get_cb("foo ");
- sprintf(buf, "foo bar %g baz", num);
- wanted = Str_new_from_trusted_utf8(buf, strlen(buf));
- CB_catf(got, "bar %f64 baz", num);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%f64");
- DECREF(wanted);
- DECREF(got);
-}
-
-static void
-test_vcatf_x32(TestBatchRunner *runner) {
- String *wanted;
- char buf[64];
- unsigned long num = INT32_MAX;
- CharBuf *got = S_get_cb("foo ");
-#if (CHY_SIZEOF_LONG == 4)
- sprintf(buf, "foo bar %.8lx baz", num);
-#elif (CHY_SIZEOF_INT == 4)
- sprintf(buf, "foo bar %.8x baz", (unsigned)num);
-#endif
- wanted = Str_new_from_trusted_utf8(buf, strlen(buf));
- CB_catf(got, "bar %x32 baz", (uint32_t)num);
- TEST_TRUE(runner, S_cb_equals(got, wanted), "%%x32");
- DECREF(wanted);
- DECREF(got);
-}
-
-typedef struct {
- CharBuf *charbuf;
- const char *pattern;
-} CatfContext;
-
-static void
-S_catf_invalid_pattern(void *vcontext) {
- CatfContext *context = (CatfContext*)vcontext;
- CB_catf(context->charbuf, context->pattern, 0);
-}
-
-static void
-test_vcatf_invalid(TestBatchRunner *runner) {
- CatfContext context;
- context.charbuf = S_get_cb("foo ");
-
- static const char *const patterns[] = {
- "bar %z baz",
- "bar %i baz",
- "bar %i1 baz",
- "bar %i33 baz",
- "bar %i65 baz",
- "bar %u baz",
- "bar %u9 baz",
- "bar %u33 baz",
- "bar %u65 baz",
- "bar %x baz",
- "bar %x9 baz",
- "bar %x33 baz",
- "bar %f baz",
- "bar %f9 baz",
- "bar %f65 baz",
- "bar \xC2 baz"
- };
- static const size_t num_patterns = sizeof(patterns) / sizeof(patterns[0]);
-
- for (size_t i = 0; i < num_patterns; i++) {
- context.pattern = patterns[i];
- Err *error = Err_trap(S_catf_invalid_pattern, &context);
- TEST_TRUE(runner, error != NULL,
- "catf throws with invalid pattern '%s'", patterns[i]);
- DECREF(error);
- }
-
- DECREF(context.charbuf);
-}
-
-static void
-test_Clear(TestBatchRunner *runner) {
- CharBuf *cb = S_get_cb("foo");
- CB_Clear(cb);
- CB_Cat_Utf8(cb, "bar", 3);
- String *string = CB_Yield_String(cb);
- TEST_TRUE(runner, Str_Equals_Utf8(string, "bar", 3), "Clear");
- DECREF(string);
- DECREF(cb);
-}
-
-static void
-test_Grow(TestBatchRunner *runner) {
- CharBuf *cb = S_get_cb("omega");
- CB_Grow(cb, 100);
- size_t cap = cb->cap;
- TEST_TRUE(runner, cap >= 100, "Grow");
- CB_Grow(cb, 100);
- TEST_UINT_EQ(runner, cb->cap, cap, "Grow to same size has no effect");
- DECREF(cb);
-}
-
-static void
-test_Get_Size(TestBatchRunner *runner) {
- CharBuf *got = S_get_cb("a");
- CB_Cat_Utf8(got, smiley, smiley_len);
- TEST_UINT_EQ(runner, CB_Get_Size(got), smiley_len + 1, "Get_Size");
- DECREF(got);
-}
-
-void
-TestCB_Run_IMP(TestCharBuf *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 41);
- test_vcatf_percent(runner);
- test_vcatf_s(runner);
- test_vcatf_s_invalid_utf8(runner);
- test_vcatf_null_string(runner);
- test_vcatf_str(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_vcatf_invalid(runner);
- test_Cat(runner);
- test_Clone(runner);
- test_Clear(runner);
- test_Grow(runner);
- test_Get_Size(runner);
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestCharBuf.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestCharBuf.cfh b/runtime/core/Clownfish/Test/TestCharBuf.cfh
deleted file mode 100644
index d568c14..0000000
--- a/runtime/core/Clownfish/Test/TestCharBuf.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::TestCharBuf nickname TestCB
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestCharBuf*
- new();
-
- void
- Run(TestCharBuf *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestClass.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestClass.c b/runtime/core/Clownfish/Test/TestClass.c
deleted file mode 100644
index a6646f8..0000000
--- a/runtime/core/Clownfish/Test/TestClass.c
+++ /dev/null
@@ -1,158 +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_BOOLEAN
-#define C_CFISH_CLASS
-#define CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "charmony.h"
-
-#include <string.h>
-
-#include "Clownfish/Test/TestClass.h"
-
-#include "Clownfish/Boolean.h"
-#include "Clownfish/Class.h"
-#include "Clownfish/Method.h"
-#include "Clownfish/String.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/Util/Memory.h"
-#include "Clownfish/Vector.h"
-
-TestClass*
-TestClass_new() {
- return (TestClass*)Class_Make_Obj(TESTCLASS);
-}
-
-#if DEBUG_CLASS_CONTENTS
-
-#include <stdio.h>
-
-static void
-S_memdump(void *vptr, size_t size) {
- unsigned char *ptr = (unsigned char*)vptr;
- for (size_t i = 0; i < size; i++) {
- printf("%02X ", ptr[i]);
- }
- printf("\n");
-}
-
-#endif /* DEBUG_CLASS_CONTENTS */
-
-static void
-test_bootstrap_idempotence(TestBatchRunner *runner) {
- Class *bool_class = BOOLEAN;
- uint32_t bool_class_size = BOOLEAN->class_alloc_size;
- uint32_t bool_ivars_offset = cfish_Bool_IVARS_OFFSET;
- Boolean *true_singleton = Bool_true_singleton;
-
- char *bool_class_contents = (char*)MALLOCATE(bool_class_size);
- memcpy(bool_class_contents, BOOLEAN, bool_class_size);
-
- // Force another bootstrap run.
- cfish_bootstrap_internal(1);
-
-#if DEBUG_CLASS_CONTENTS
- printf("Before\n");
- S_memdump(bool_class_contents, bool_class_size);
- printf("After\n");
- S_memdump(BOOLEAN, bool_class_size);
-#endif
-
- TEST_TRUE(runner, bool_class == BOOLEAN,
- "Boolean class pointer unchanged");
- TEST_TRUE(runner,
- memcmp(bool_class_contents, BOOLEAN, bool_class_size) == 0,
- "Boolean class unchanged");
- TEST_TRUE(runner, bool_ivars_offset == cfish_Bool_IVARS_OFFSET,
- "Boolean ivars offset unchanged");
- TEST_TRUE(runner, true_singleton == Bool_true_singleton,
- "Boolean singleton unchanged");
-
- FREEMEM(bool_class_contents);
-}
-
-static String*
-MyObj_To_String_IMP(Obj *self) {
- UNUSED_VAR(self);
- return Str_newf("delta");
-}
-
-static void
-test_simple_subclass(TestBatchRunner *runner) {
- String *class_name = SSTR_WRAP_C("Clownfish::Test::MyObj");
- Class *subclass = Class_singleton(class_name, OBJ);
-
- TEST_TRUE(runner, Str_Equals(Class_Get_Name(subclass), (Obj*)class_name),
- "Get_Name");
- TEST_TRUE(runner, Class_Get_Parent(subclass) == OBJ, "Get_Parent");
-
- Obj *obj = Class_Make_Obj(subclass);
- TEST_TRUE(runner, Obj_is_a(obj, subclass), "Make_Obj");
-
- Class_Override(subclass, (cfish_method_t)MyObj_To_String_IMP,
- CFISH_Obj_To_String_OFFSET);
- String *str = Obj_To_String(obj);
- TEST_TRUE(runner, Str_Equals_Utf8(str, "delta", 5), "Override");
- DECREF(str);
-
- DECREF(obj);
-}
-
-static void
-test_add_alias_to_registry(TestBatchRunner *runner) {
- static const char alias[] = "Clownfish::Test::ObjAlias";
- bool added;
-
- added = Class_add_alias_to_registry(OBJ, alias, sizeof(alias) - 1);
- TEST_TRUE(runner, added, "add_alias_to_registry returns true");
- Class *klass = Class_fetch_class(SSTR_WRAP_C(alias));
- TEST_TRUE(runner, klass == OBJ, "add_alias_to_registry works");
-
- added = Class_add_alias_to_registry(CLASS, alias, sizeof(alias) - 1);
- TEST_FALSE(runner, added, "add_alias_to_registry returns false");
-}
-
-static void
-test_Get_Methods(TestBatchRunner *runner) {
- Vector *methods = Class_Get_Methods(OBJ);
- Method *destroy = NULL;
-
- for (size_t i = 0, size = Vec_Get_Size(methods); i < size; i++) {
- Method *method = (Method*)Vec_Fetch(methods, i);
-
- if (Str_Equals_Utf8(Method_Get_Name(method), "Destroy", 7)) {
- destroy = method;
- }
- }
-
- TEST_TRUE(runner, destroy != NULL, "Destroy method found");
-
- DECREF(methods);
-}
-
-void
-TestClass_Run_IMP(TestClass *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 12);
- test_bootstrap_idempotence(runner);
- test_simple_subclass(runner);
- test_add_alias_to_registry(runner);
- test_Get_Methods(runner);
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestClass.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestClass.cfh b/runtime/core/Clownfish/Test/TestClass.cfh
deleted file mode 100644
index 615c34e..0000000
--- a/runtime/core/Clownfish/Test/TestClass.cfh
+++ /dev/null
@@ -1,28 +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 TestClownfish;
-
-class Clownfish::Test::TestClass
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestClass*
- new();
-
- void
- Run(TestClass *self, TestBatchRunner *runner);
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestErr.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestErr.c b/runtime/core/Clownfish/Test/TestErr.c
deleted file mode 100644
index 46ecb1e..0000000
--- a/runtime/core/Clownfish/Test/TestErr.c
+++ /dev/null
@@ -1,193 +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 CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestErr.h"
-
-#include "Clownfish/String.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Class.h"
-
-TestErr*
-TestErr_new() {
- return (TestErr*)Class_Make_Obj(TESTERR);
-}
-
-static void
-test_To_String(TestBatchRunner *runner) {
- String *message = Str_newf("oops");
- Err *error = Err_new(message);
- String *string = Err_To_String(error);
- TEST_TRUE(runner, Str_Equals(message, (Obj*)string),
- "Stringifies as message");
- DECREF(string);
- DECREF(error);
-}
-
-static void
-test_Cat_Mess(TestBatchRunner *runner) {
- Err *error = Err_new(Str_newf("alpha"));
- Err_Cat_Mess(error, SSTR_WRAP_C("\nbeta"));
- String *mess = Err_Get_Mess(error);
- TEST_TRUE(runner, Str_Equals_Utf8(mess, "alpha\nbeta", 10), "Cat_Mess");
- DECREF(error);
-}
-
-static void
-test_Add_Frame(TestBatchRunner *runner) {
- {
- Err *error = Err_new(Str_newf("alpha"));
- Err_Add_Frame(error, "source.c", 128, "function");
- String *mess = Err_Get_Mess(error);
- const char *expected = "alpha\n\tfunction at source.c line 128\n";
- TEST_TRUE(runner, Str_Equals_Utf8(mess, expected, strlen(expected)),
- "Add_Frame");
- DECREF(error);
- }
-
- {
- Err *error = Err_new(Str_newf("alpha\n"));
- Err_Add_Frame(error, "source.c", 128, "function");
- String *mess = Err_Get_Mess(error);
- const char *expected = "alpha\n\tfunction at source.c line 128\n";
- TEST_TRUE(runner, Str_Equals_Utf8(mess, expected, strlen(expected)),
- "Add_Frame with trailing newline");
- DECREF(error);
- }
-
- {
- Err *error = Err_new(Str_newf("alpha"));
- Err_Add_Frame(error, "source.c", 128, NULL);
- String *mess = Err_Get_Mess(error);
- const char *expected = "alpha\n\tat source.c line 128\n";
- TEST_TRUE(runner, Str_Equals_Utf8(mess, expected, strlen(expected)),
- "Add_Frame without func");
- DECREF(error);
- }
-}
-
-static void
-S_rethrow(void *context) {
- Err *error = (Err*)context;
- Err_rethrow(error, "src.c", 12, "fn");
-}
-
-static void
-test_rethrow(TestBatchRunner *runner) {
- Err *error = Err_new(Str_newf("error"));
- Err *rethrown = Err_trap(S_rethrow, error);
- String *mess = Err_Get_Mess(rethrown);
- const char *expected = "error\n\tfn at src.c line 12\n";
- TEST_TRUE(runner, Str_Starts_With_Utf8(mess, expected, strlen(expected)),
- "rethrow");
- DECREF(error);
-}
-
-static void
-S_invalid_downcast(void *context) {
- Obj *obj = (Obj*)context;
- DOWNCAST(obj, ERR);
-}
-
-static void
-test_downcast(TestBatchRunner *runner) {
- Obj *obj = (Obj*)Str_newf("gamma");
-
- TEST_TRUE(runner, DOWNCAST(obj, STRING) != NULL, "downcast");
-
- TEST_TRUE(runner, DOWNCAST(NULL, STRING) == NULL, "downcast NULL");
-
- Err *error = Err_trap(S_invalid_downcast, obj);
- TEST_TRUE(runner, error != NULL, "downcast throws");
- DECREF(error);
-
- DECREF(obj);
-}
-
-static void
-S_invalid_certify(void *context) {
- Obj *obj = (Obj*)context;
- CERTIFY(obj, ERR);
-}
-
-static void
-test_certify(TestBatchRunner *runner) {
- Obj *obj = (Obj*)Str_newf("epsilon");
- Err *error;
-
- TEST_TRUE(runner, CERTIFY(obj, STRING) != NULL, "certify");
-
- error = Err_trap(S_invalid_certify, NULL);
- TEST_TRUE(runner, error != NULL, "certify NULL");
- DECREF(error);
-
- error = Err_trap(S_invalid_certify, obj);
- TEST_TRUE(runner, error != NULL, "certify throws");
- DECREF(error);
-
- DECREF(obj);
-}
-
-static void
-S_err_thread(void *arg) {
- TestBatchRunner *runner = (TestBatchRunner*)arg;
-
- TEST_TRUE(runner, Err_get_error() == NULL,
- "global error in thread initialized to null");
-
- Err_set_error(Err_new(Str_newf("thread")));
- String *mess = Err_Get_Mess(Err_get_error());
- TEST_TRUE(runner, Str_Equals_Utf8(mess, "thread", 6),
- "set_error in thread works");
-}
-
-static void
-test_threads(TestBatchRunner *runner) {
- if (!TestUtils_has_threads) {
- SKIP(runner, 3, "no thread support");
- return;
- }
-
- Err_set_error(Err_new(Str_newf("main")));
-
- void *runtime = TestUtils_clone_host_runtime();
- Thread *thread = TestUtils_thread_create(S_err_thread, runner, runtime);
- TestUtils_thread_join(thread);
- TestUtils_destroy_host_runtime(runtime);
-
- String *mess = Err_Get_Mess(Err_get_error());
- TEST_TRUE(runner, Str_Equals_Utf8(mess, "main", 4),
- "thread doesn't clobber global error");
-}
-
-void
-TestErr_Run_IMP(TestErr *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 15);
- test_To_String(runner);
- test_Cat_Mess(runner);
- test_Add_Frame(runner);
- test_rethrow(runner);
- test_downcast(runner);
- test_certify(runner);
- test_threads(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestErr.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestErr.cfh b/runtime/core/Clownfish/Test/TestErr.cfh
deleted file mode 100644
index 178017c..0000000
--- a/runtime/core/Clownfish/Test/TestErr.cfh
+++ /dev/null
@@ -1,28 +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 TestClownfish;
-
-class Clownfish::Test::TestErr
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestErr*
- new();
-
- void
- Run(TestErr *self, TestBatchRunner *runner);
-}
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestHash.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestHash.c b/runtime/core/Clownfish/Test/TestHash.c
deleted file mode 100644
index b00d891..0000000
--- a/runtime/core/Clownfish/Test/TestHash.c
+++ /dev/null
@@ -1,325 +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 <time.h>
-
-#define CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-#define C_CFISH_HASH
-
-#include "Clownfish/Test/TestHash.h"
-
-#include "Clownfish/String.h"
-#include "Clownfish/Boolean.h"
-#include "Clownfish/Hash.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Vector.h"
-#include "Clownfish/Class.h"
-
-TestHash*
-TestHash_new() {
- return (TestHash*)Class_Make_Obj(TESTHASH);
-}
-
-static void
-test_Equals(TestBatchRunner *runner) {
- Hash *hash = Hash_new(0);
- Hash *other = Hash_new(0);
- String *stuff = SSTR_WRAP_C("stuff");
-
- TEST_TRUE(runner, Hash_Equals(hash, (Obj*)other),
- "Empty hashes are equal");
-
- Hash_Store_Utf8(hash, "foo", 3, (Obj*)CFISH_TRUE);
- TEST_FALSE(runner, Hash_Equals(hash, (Obj*)other),
- "Add one pair and Equals returns false");
-
- Hash_Store_Utf8(other, "foo", 3, (Obj*)CFISH_TRUE);
- TEST_TRUE(runner, Hash_Equals(hash, (Obj*)other),
- "Add a matching pair and Equals returns true");
-
- Hash_Store_Utf8(other, "foo", 3, INCREF(stuff));
- TEST_FALSE(runner, Hash_Equals(hash, (Obj*)other),
- "Non-matching value spoils Equals");
-
- DECREF(hash);
- DECREF(other);
-}
-
-static void
-test_Store_and_Fetch(TestBatchRunner *runner) {
- Hash *hash = Hash_new(100);
- Hash *dupe = Hash_new(100);
- const size_t starting_cap = Hash_Get_Capacity(hash);
- Vector *expected = Vec_new(100);
- Vector *got = Vec_new(100);
- String *twenty = SSTR_WRAP_C("20");
- String *forty = SSTR_WRAP_C("40");
- String *foo = SSTR_WRAP_C("foo");
-
- for (int32_t i = 0; i < 100; i++) {
- String *str = Str_newf("%i32", i);
- Hash_Store(hash, str, (Obj*)str);
- Hash_Store(dupe, str, INCREF(str));
- Vec_Push(expected, INCREF(str));
- }
- TEST_TRUE(runner, Hash_Equals(hash, (Obj*)dupe), "Equals");
-
- TEST_UINT_EQ(runner, Hash_Get_Capacity(hash), starting_cap,
- "Initial capacity sufficient (no rebuilds)");
-
- for (size_t i = 0; i < 100; i++) {
- String *key = (String*)Vec_Fetch(expected, i);
- Obj *elem = Hash_Fetch(hash, key);
- Vec_Push(got, (Obj*)INCREF(elem));
- }
-
- TEST_TRUE(runner, Vec_Equals(got, (Obj*)expected),
- "basic Store and Fetch");
- TEST_UINT_EQ(runner, Hash_Get_Size(hash), 100,
- "size incremented properly by Hash_Store");
-
- TEST_TRUE(runner, Hash_Fetch(hash, foo) == NULL,
- "Fetch against non-existent key returns NULL");
-
- String *twelve = (String*)Hash_Fetch_Utf8(hash, "12", 2);
- TEST_TRUE(runner, Str_Equals_Utf8(twelve, "12", 2), "Fetch_Utf8");
-
- Obj *stored_foo = INCREF(foo);
- Hash_Store(hash, forty, stored_foo);
- TEST_TRUE(runner, Str_Equals(foo, Hash_Fetch(hash, forty)),
- "Hash_Store replaces existing value");
- TEST_FALSE(runner, Hash_Equals(hash, (Obj*)dupe),
- "replacement value spoils equals");
- TEST_UINT_EQ(runner, Hash_Get_Size(hash), 100,
- "size unaffected after value replaced");
-
- TEST_TRUE(runner, Hash_Delete(hash, forty) == stored_foo,
- "Delete returns value");
- DECREF(stored_foo);
- TEST_UINT_EQ(runner, Hash_Get_Size(hash), 99,
- "size decremented by successful Delete");
- TEST_TRUE(runner, Hash_Delete(hash, forty) == NULL,
- "Delete returns NULL when key not found");
- TEST_UINT_EQ(runner, Hash_Get_Size(hash), 99,
- "size not decremented by unsuccessful Delete");
- DECREF(Hash_Delete(dupe, forty));
- TEST_TRUE(runner, Vec_Equals(got, (Obj*)expected), "Equals after Delete");
-
- Obj *forty_one = Hash_Delete_Utf8(hash, "41", 2);
- TEST_TRUE(runner, forty_one != NULL, "Delete_Utf8");
- TEST_UINT_EQ(runner, Hash_Get_Size(hash), 98,
- "Delete_Utf8 decrements size");
- DECREF(forty_one);
-
- Hash_Clear(hash);
- TEST_TRUE(runner, Hash_Fetch(hash, twenty) == NULL, "Clear");
- TEST_TRUE(runner, Hash_Get_Size(hash) == 0, "size is 0 after Clear");
-
- Hash_Clear(hash);
- Hash_Store(hash, forty, NULL);
- TEST_TRUE(runner, Hash_Fetch(hash, forty) == NULL, "Store NULL");
- TEST_TRUE(runner, Hash_Get_Size(hash) == 1, "Size after Store NULL");
- TEST_TRUE(runner, Hash_Delete(hash, forty) == NULL, "Delete NULL value");
- TEST_TRUE(runner, Hash_Get_Size(hash) == 0,
- "Size after Deleting NULL val");
-
- DECREF(hash);
- DECREF(dupe);
- DECREF(got);
- DECREF(expected);
-}
-
-static void
-test_Keys_Values(TestBatchRunner *runner) {
- Hash *hash = Hash_new(0); // trigger multiple rebuilds.
- Vector *expected = Vec_new(100);
- Vector *keys;
- Vector *values;
-
- for (uint32_t i = 0; i < 500; i++) {
- String *str = Str_newf("%u32", i);
- Hash_Store(hash, str, (Obj*)str);
- Vec_Push(expected, INCREF(str));
- }
-
- Vec_Sort(expected);
-
- keys = Hash_Keys(hash);
- values = Hash_Values(hash);
- Vec_Sort(keys);
- Vec_Sort(values);
- TEST_TRUE(runner, Vec_Equals(keys, (Obj*)expected), "Keys");
- TEST_TRUE(runner, Vec_Equals(values, (Obj*)expected), "Values");
- Vec_Clear(keys);
- Vec_Clear(values);
-
- {
- String *forty = SSTR_WRAP_C("40");
- String *nope = SSTR_WRAP_C("nope");
- TEST_TRUE(runner, Hash_Has_Key(hash, forty), "Has_Key");
- TEST_FALSE(runner, Hash_Has_Key(hash, nope),
- "Has_Key returns false for non-existent key");
- }
-
- DECREF(hash);
- DECREF(expected);
- DECREF(keys);
- DECREF(values);
-}
-
-static void
-test_stress(TestBatchRunner *runner) {
- Hash *hash = Hash_new(0); // trigger multiple rebuilds.
- Vector *expected = Vec_new(1000);
- Vector *keys;
- Vector *values;
-
- for (uint32_t i = 0; i < 1000; i++) {
- String *str = TestUtils_random_string((size_t)(rand() % 1200));
- while (Hash_Fetch(hash, str)) {
- DECREF(str);
- str = TestUtils_random_string((size_t)(rand() % 1200));
- }
- Hash_Store(hash, str, (Obj*)str);
- Vec_Push(expected, INCREF(str));
- }
-
- Vec_Sort(expected);
-
- // Overwrite for good measure.
- for (uint32_t i = 0; i < 1000; i++) {
- String *str = (String*)Vec_Fetch(expected, i);
- Hash_Store(hash, str, INCREF(str));
- }
-
- keys = Hash_Keys(hash);
- values = Hash_Values(hash);
- Vec_Sort(keys);
- Vec_Sort(values);
- TEST_TRUE(runner, Vec_Equals(keys, (Obj*)expected), "stress Keys");
- TEST_TRUE(runner, Vec_Equals(values, (Obj*)expected), "stress Values");
-
- DECREF(keys);
- DECREF(values);
- DECREF(expected);
- DECREF(hash);
-}
-
-static void
-test_collision(TestBatchRunner *runner) {
- Hash *hash = Hash_new(0);
- String *one = Str_newf("A");
- String *two = Str_newf("P{2}|=~-ULE/d");
-
- TEST_TRUE(runner, Str_Hash_Sum(one) == Str_Hash_Sum(two),
- "Keys have the same hash sum");
-
- Hash_Store(hash, one, INCREF(one));
- Hash_Store(hash, two, INCREF(two));
- String *elem = (String*)Hash_Fetch(hash, two);
- TEST_TRUE(runner, elem == two, "Fetch works with collisions");
-
- DECREF(one);
- DECREF(two);
- DECREF(hash);
-}
-
-static void
-test_store_skips_tombstone(TestBatchRunner *runner) {
- Hash *hash = Hash_new(0);
- size_t mask = Hash_Get_Capacity(hash) - 1;
-
- String *one = Str_newf("one");
- size_t slot = Str_Hash_Sum(one) & mask;
-
- // Find a colliding key.
- String *two = NULL;
- for (int i = 0; i < 100000; i++) {
- two = Str_newf("%i32", i);
- if (slot == (Str_Hash_Sum(two) & mask)) {
- break;
- }
- DECREF(two);
- two = NULL;
- }
-
- Hash_Store(hash, one, (Obj*)CFISH_TRUE);
- Hash_Store(hash, two, (Obj*)CFISH_TRUE);
- Hash_Delete(hash, one);
- Hash_Store(hash, two, (Obj*)CFISH_TRUE);
-
- TEST_UINT_EQ(runner, Hash_Get_Size(hash), 1, "Store skips tombstone");
-
- DECREF(one);
- DECREF(two);
- DECREF(hash);
-}
-
-static void
-test_threshold_accounting(TestBatchRunner *runner) {
- Hash *hash = Hash_new(20);
- String *key = Str_newf("key");
-
- size_t threshold = hash->threshold;
- Hash_Store(hash, key, (Obj*)CFISH_TRUE);
- Hash_Delete(hash, key);
- TEST_UINT_EQ(runner, hash->threshold, threshold - 1,
- "Tombstone creation decreases threshold");
-
- Hash_Store(hash, key, (Obj*)CFISH_TRUE);
- TEST_UINT_EQ(runner, hash->threshold, threshold,
- "Tombstone destruction increases threshold");
-
- DECREF(key);
- DECREF(hash);
-}
-
-static void
-test_tombstone_identification(TestBatchRunner *runner) {
- Hash *hash = Hash_new(20);
- String *key = Str_newf("P{2}|=~-U@!y>");
-
- // Tombstones have a zero hash_sum.
- TEST_UINT_EQ(runner, Str_Hash_Sum(key), 0, "Key has zero hash sum");
-
- Hash_Store(hash, key, (Obj*)CFISH_TRUE);
- Hash_Delete(hash, key);
- TEST_TRUE(runner, Hash_Fetch(hash, key) == NULL,
- "Key with zero hash sum isn't mistaken for tombstone");
-
- DECREF(key);
- DECREF(hash);
-}
-
-void
-TestHash_Run_IMP(TestHash *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 39);
- srand((unsigned int)time((time_t*)NULL));
- test_Equals(runner);
- test_Store_and_Fetch(runner);
- test_Keys_Values(runner);
- test_stress(runner);
- test_collision(runner);
- test_store_skips_tombstone(runner);
- test_threshold_accounting(runner);
- test_tombstone_identification(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestHash.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestHash.cfh b/runtime/core/Clownfish/Test/TestHash.cfh
deleted file mode 100644
index a730105..0000000
--- a/runtime/core/Clownfish/Test/TestHash.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::TestHash
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestHash*
- new();
-
- void
- Run(TestHash *self, TestBatchRunner *runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestHashIterator.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestHashIterator.c b/runtime/core/Clownfish/Test/TestHashIterator.c
deleted file mode 100644
index fac7d69..0000000
--- a/runtime/core/Clownfish/Test/TestHashIterator.c
+++ /dev/null
@@ -1,253 +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 <time.h>
-
-#define CFISH_USE_SHORT_NAMES
-#define TESTCFISH_USE_SHORT_NAMES
-
-#include "Clownfish/Test/TestHashIterator.h"
-
-#include "Clownfish/Err.h"
-#include "Clownfish/String.h"
-#include "Clownfish/Hash.h"
-#include "Clownfish/HashIterator.h"
-#include "Clownfish/Test.h"
-#include "Clownfish/Vector.h"
-#include "Clownfish/TestHarness/TestBatchRunner.h"
-#include "Clownfish/TestHarness/TestUtils.h"
-#include "Clownfish/Class.h"
-
-TestHashIterator*
-TestHashIterator_new() {
- return (TestHashIterator*)Class_Make_Obj(TESTHASHITERATOR);
-}
-
-static void
-test_Next(TestBatchRunner *runner) {
- Hash *hash = Hash_new(0); // trigger multiple rebuilds.
- Vector *expected = Vec_new(100);
- Vector *keys = Vec_new(500);
- Vector *values = Vec_new(500);
-
- for (uint32_t i = 0; i < 500; i++) {
- String *str = Str_newf("%u32", i);
- Hash_Store(hash, str, (Obj*)str);
- Vec_Push(expected, INCREF(str));
- }
-
- Vec_Sort(expected);
-
- {
- HashIterator *iter = HashIter_new(hash);
- while (HashIter_Next(iter)) {
- String *key = HashIter_Get_Key(iter);
- Obj *value = HashIter_Get_Value(iter);
- Vec_Push(keys, INCREF(key));
- Vec_Push(values, INCREF(value));
- }
- TEST_TRUE(runner, !HashIter_Next(iter),
- "Next continues to return false after iteration finishes.");
-
- DECREF(iter);
- }
-
- Vec_Sort(keys);
- Vec_Sort(values);
- TEST_TRUE(runner, Vec_Equals(keys, (Obj*)expected), "Keys from Iter");
- TEST_TRUE(runner, Vec_Equals(values, (Obj*)expected), "Values from Iter");
-
- DECREF(hash);
- DECREF(expected);
- DECREF(keys);
- DECREF(values);
-}
-
-static void
-S_invoke_Next(void *context) {
- HashIterator *iter = (HashIterator*)context;
- HashIter_Next(iter);
-}
-
-static void
-S_invoke_Get_Key(void *context) {
- HashIterator *iter = (HashIterator*)context;
- HashIter_Get_Key(iter);
-}
-
-static void
-S_invoke_Get_Value(void *context) {
- HashIterator *iter = (HashIterator*)context;
- HashIter_Get_Value(iter);
-}
-
-static void
-test_empty(TestBatchRunner *runner) {
- Hash *hash = Hash_new(0);
- HashIterator *iter = HashIter_new(hash);
-
- TEST_TRUE(runner, !HashIter_Next(iter),
- "First call to next false on empty hash iteration");
-
- Err *get_key_error = Err_trap(S_invoke_Get_Key, iter);
- TEST_TRUE(runner, get_key_error != NULL,
- "Get_Key throws exception on empty hash.");
- DECREF(get_key_error);
-
- Err *get_value_error = Err_trap(S_invoke_Get_Value, iter);
- TEST_TRUE(runner, get_value_error != NULL,
- "Get_Value throws exception on empty hash.");
- DECREF(get_value_error);
-
- DECREF(hash);
- DECREF(iter);
-}
-
-static void
-test_Get_Key_and_Get_Value(TestBatchRunner *runner) {
- Hash *hash = Hash_new(0);
- String *str = Str_newf("foo");
- Hash_Store(hash, str, (Obj*)str);
- bool ok;
-
- HashIterator *iter = HashIter_new(hash);
- DECREF(hash);
-
- Err *get_key_error = Err_trap(S_invoke_Get_Key, iter);
- TEST_TRUE(runner, get_key_error != NULL,
- "Get_Key throws exception before first call to Next.");
- ok = Str_Contains_Utf8(Err_Get_Mess(get_key_error), "before", 6);
- TEST_TRUE(runner, ok, "Get_Key before Next throws correct message");
- DECREF(get_key_error);
-
- Err *get_value_error = Err_trap(S_invoke_Get_Value, iter);
- TEST_TRUE(runner, get_value_error != NULL,
- "Get_Value throws exception before first call to Next.");
- ok = Str_Contains_Utf8(Err_Get_Mess(get_value_error), "before", 6);
- TEST_TRUE(runner, ok, "Get_Value before Next throws correct message");
- DECREF(get_value_error);
-
- HashIter_Next(iter);
- TEST_TRUE(runner, HashIter_Get_Key(iter) != NULL,
- "Get_Key during iteration.");
- TEST_TRUE(runner, HashIter_Get_Value(iter) != NULL,
- "Get_Value during iteration.");
-
- HashIter_Next(iter);
- get_key_error = Err_trap(S_invoke_Get_Key, iter);
- TEST_TRUE(runner, get_key_error != NULL,
- "Get_Key throws exception after end of iteration.");
- ok = Str_Contains_Utf8(Err_Get_Mess(get_key_error), "after", 5);
- TEST_TRUE(runner, ok, "Get_Key after end throws correct message");
- DECREF(get_key_error);
-
- get_value_error = Err_trap(S_invoke_Get_Value, iter);
- TEST_TRUE(runner, get_value_error != NULL,
- "Get_Value throws exception after end of iteration.");
- ok = Str_Contains_Utf8(Err_Get_Mess(get_value_error), "after", 5);
- TEST_TRUE(runner, ok, "Get_Value after end throws correct message");
- DECREF(get_value_error);
-
-
- DECREF(iter);
-}
-
-static void
-test_illegal_modification(TestBatchRunner *runner) {
- Hash *hash = Hash_new(0);
-
- for (uint32_t i = 0; i < 3; i++) {
- String *str = Str_newf("%u32", i);
- Hash_Store(hash, str, (Obj*)str);
- }
-
- HashIterator *iter = HashIter_new(hash);
- HashIter_Next(iter);
-
- for (uint32_t i = 0; i < 100; i++) {
- String *str = Str_newf("foo %u32", i);
- Hash_Store(hash, str, (Obj*)str);
- }
-
- Err *next_error = Err_trap(S_invoke_Next, iter);
- TEST_TRUE(runner, next_error != NULL,
- "Next on resized hash throws exception.");
- DECREF(next_error);
-
- Err *get_key_error = Err_trap(S_invoke_Get_Key, iter);
- TEST_TRUE(runner, get_key_error != NULL,
- "Get_Key on resized hash throws exception.");
- DECREF(get_key_error);
-
- Err *get_value_error = Err_trap(S_invoke_Get_Value, iter);
- TEST_TRUE(runner, get_value_error != NULL,
- "Get_Value on resized hash throws exception.");
- DECREF(get_value_error);
-
- DECREF(hash);
- DECREF(iter);
-}
-
-static void
-test_tombstone(TestBatchRunner *runner) {
- {
- Hash *hash = Hash_new(0);
- String *str = Str_newf("foo");
- Hash_Store(hash, str, INCREF(str));
- DECREF(Hash_Delete(hash, str));
- DECREF(str);
-
- HashIterator *iter = HashIter_new(hash);
- TEST_TRUE(runner, !HashIter_Next(iter), "Next advances past tombstones.");
-
- DECREF(iter);
- DECREF(hash);
- }
-
- {
- Hash *hash = Hash_new(0);
- String *str = Str_newf("foo");
- Hash_Store(hash, str, INCREF(str));
-
- HashIterator *iter = HashIter_new(hash);
- HashIter_Next(iter);
- DECREF(Hash_Delete(hash, str));
-
-
- Err *get_key_error = Err_trap(S_invoke_Get_Key, iter);
- TEST_TRUE(runner, get_key_error != NULL,
- "Get_Key doesn't return tombstone and throws error.");
- DECREF(get_key_error);
-
- DECREF(str);
- DECREF(iter);
- DECREF(hash);
- }
-}
-
-void
-TestHashIterator_Run_IMP(TestHashIterator *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 21);
- srand((unsigned int)time((time_t*)NULL));
- test_Next(runner);
- test_empty(runner);
- test_Get_Key_and_Get_Value(runner);
- test_illegal_modification(runner);
- test_tombstone(runner);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/core/Clownfish/Test/TestHashIterator.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Test/TestHashIterator.cfh b/runtime/core/Clownfish/Test/TestHashIterator.cfh
deleted file mode 100644
index 4765f76..0000000
--- a/runtime/core/Clownfish/Test/TestHashIterator.cfh
+++ /dev/null
@@ -1,29 +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 TestClownfish;
-
-class Clownfish::Test::TestHashIterator
- inherits Clownfish::TestHarness::TestBatch {
-
- inert incremented TestHashIterator*
- new();
-
- void
- Run(TestHashIterator *self, TestBatchRunner *runner);
-}
-
-
[14/14] lucy-clownfish git commit: Merge branch 'separate-tests'
Posted by nw...@apache.org.
Merge branch 'separate-tests'
This brings the size of the Clownfish library down to 95 KB on
32-bit Ubuntu (with -fno-asynchronous-unwind-tables), 88 KB on
64-bit Windows, and 82 KB on OS X.
Fixes CLOWNFISH-80.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/0be314b9
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/0be314b9
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/0be314b9
Branch: refs/heads/master
Commit: 0be314b9d4d306f019a6b79c6bd9d90118679af3
Parents: 56f1982 a45abf0
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon Jul 11 13:24:03 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Mon Jul 11 13:24:03 2016 +0200
----------------------------------------------------------------------
compiler/perl/Build.PL | 2 +-
compiler/perl/lib/Clownfish/CFC/Perl/Build.pm | 28 +-
runtime/c/.gitignore | 21 +-
runtime/common/charmonizer.c | 195 +++--
runtime/common/charmonizer.main | 197 +++--
runtime/core/Clownfish/LockFreeRegistry.h | 10 +-
runtime/core/Clownfish/PtrHash.h | 10 +-
runtime/core/Clownfish/Test.c | 70 --
runtime/core/Clownfish/Test.cfh | 26 -
runtime/core/Clownfish/Test/TestBlob.c | 147 ----
runtime/core/Clownfish/Test/TestBlob.cfh | 28 -
runtime/core/Clownfish/Test/TestBoolean.c | 99 ---
runtime/core/Clownfish/Test/TestBoolean.cfh | 29 -
runtime/core/Clownfish/Test/TestByteBuf.c | 218 -----
runtime/core/Clownfish/Test/TestByteBuf.cfh | 29 -
runtime/core/Clownfish/Test/TestCharBuf.c | 394 ---------
runtime/core/Clownfish/Test/TestCharBuf.cfh | 29 -
runtime/core/Clownfish/Test/TestClass.c | 158 ----
runtime/core/Clownfish/Test/TestClass.cfh | 28 -
runtime/core/Clownfish/Test/TestErr.c | 193 -----
runtime/core/Clownfish/Test/TestErr.cfh | 28 -
runtime/core/Clownfish/Test/TestHash.c | 325 -------
runtime/core/Clownfish/Test/TestHash.cfh | 29 -
runtime/core/Clownfish/Test/TestHashIterator.c | 253 ------
.../core/Clownfish/Test/TestHashIterator.cfh | 29 -
runtime/core/Clownfish/Test/TestHost.c | 125 ---
runtime/core/Clownfish/Test/TestHost.cfh | 81 --
.../core/Clownfish/Test/TestLockFreeRegistry.c | 168 ----
.../Clownfish/Test/TestLockFreeRegistry.cfh | 29 -
runtime/core/Clownfish/Test/TestMethod.c | 91 --
runtime/core/Clownfish/Test/TestMethod.cfh | 28 -
runtime/core/Clownfish/Test/TestNum.c | 278 ------
runtime/core/Clownfish/Test/TestNum.cfh | 29 -
runtime/core/Clownfish/Test/TestObj.c | 152 ----
runtime/core/Clownfish/Test/TestObj.cfh | 28 -
runtime/core/Clownfish/Test/TestPtrHash.c | 108 ---
runtime/core/Clownfish/Test/TestPtrHash.cfh | 29 -
runtime/core/Clownfish/Test/TestString.c | 848 -------------------
runtime/core/Clownfish/Test/TestString.cfh | 36 -
runtime/core/Clownfish/Test/TestVector.c | 572 -------------
runtime/core/Clownfish/Test/TestVector.cfh | 29 -
runtime/core/Clownfish/Test/Util/TestAtomic.c | 65 --
runtime/core/Clownfish/Test/Util/TestAtomic.cfh | 29 -
runtime/core/Clownfish/Test/Util/TestMemory.c | 119 ---
runtime/core/Clownfish/Test/Util/TestMemory.cfh | 29 -
.../core/Clownfish/Test/Util/TestStringHelper.c | 373 --------
.../Clownfish/Test/Util/TestStringHelper.cfh | 29 -
runtime/core/Clownfish/Util/Atomic.h | 4 +-
runtime/core/TestClownfish.c | 22 -
runtime/core/TestClownfish.cfp | 8 -
runtime/go/build.go | 4 +-
runtime/perl/.gitignore | 2 +
runtime/perl/Build.PL | 2 +-
runtime/perl/buildlib/Clownfish/Build.pm | 26 +-
.../perl/buildlib/Clownfish/Build/Binding.pm | 2 +-
runtime/perl/lib/Clownfish/Test.pm | 8 +
runtime/perl/t/binding/019-obj.t | 1 +
runtime/perl/t/binding/023-string.t | 1 +
runtime/python/cfext/CFBind.c | 1 +
runtime/python/setup.py | 13 +-
runtime/test/Clownfish/Test.c | 70 ++
runtime/test/Clownfish/Test.cfh | 26 +
runtime/test/Clownfish/Test/TestBlob.c | 147 ++++
runtime/test/Clownfish/Test/TestBlob.cfh | 28 +
runtime/test/Clownfish/Test/TestBoolean.c | 99 +++
runtime/test/Clownfish/Test/TestBoolean.cfh | 29 +
runtime/test/Clownfish/Test/TestByteBuf.c | 218 +++++
runtime/test/Clownfish/Test/TestByteBuf.cfh | 29 +
runtime/test/Clownfish/Test/TestCharBuf.c | 394 +++++++++
runtime/test/Clownfish/Test/TestCharBuf.cfh | 29 +
runtime/test/Clownfish/Test/TestClass.c | 164 ++++
runtime/test/Clownfish/Test/TestClass.cfh | 28 +
runtime/test/Clownfish/Test/TestErr.c | 193 +++++
runtime/test/Clownfish/Test/TestErr.cfh | 28 +
runtime/test/Clownfish/Test/TestHash.c | 325 +++++++
runtime/test/Clownfish/Test/TestHash.cfh | 29 +
runtime/test/Clownfish/Test/TestHashIterator.c | 253 ++++++
.../test/Clownfish/Test/TestHashIterator.cfh | 29 +
runtime/test/Clownfish/Test/TestHost.c | 125 +++
runtime/test/Clownfish/Test/TestHost.cfh | 81 ++
.../test/Clownfish/Test/TestLockFreeRegistry.c | 168 ++++
.../Clownfish/Test/TestLockFreeRegistry.cfh | 29 +
runtime/test/Clownfish/Test/TestMethod.c | 91 ++
runtime/test/Clownfish/Test/TestMethod.cfh | 28 +
runtime/test/Clownfish/Test/TestNum.c | 278 ++++++
runtime/test/Clownfish/Test/TestNum.cfh | 29 +
runtime/test/Clownfish/Test/TestObj.c | 152 ++++
runtime/test/Clownfish/Test/TestObj.cfh | 28 +
runtime/test/Clownfish/Test/TestPtrHash.c | 108 +++
runtime/test/Clownfish/Test/TestPtrHash.cfh | 29 +
runtime/test/Clownfish/Test/TestString.c | 848 +++++++++++++++++++
runtime/test/Clownfish/Test/TestString.cfh | 36 +
runtime/test/Clownfish/Test/TestVector.c | 572 +++++++++++++
runtime/test/Clownfish/Test/TestVector.cfh | 29 +
runtime/test/Clownfish/Test/Util/TestAtomic.c | 65 ++
runtime/test/Clownfish/Test/Util/TestAtomic.cfh | 29 +
runtime/test/Clownfish/Test/Util/TestMemory.c | 119 +++
runtime/test/Clownfish/Test/Util/TestMemory.cfh | 29 +
.../test/Clownfish/Test/Util/TestStringHelper.c | 373 ++++++++
.../Clownfish/Test/Util/TestStringHelper.cfh | 29 +
runtime/test/TestClownfish.c | 22 +
runtime/test/TestClownfish.cfp | 8 +
102 files changed, 5792 insertions(+), 5575 deletions(-)
----------------------------------------------------------------------
[06/14] lucy-clownfish git commit: Move tests to separate directory
Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestClass.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestClass.c b/runtime/test/Clownfish/Test/TestClass.c
new file mode 100644
index 0000000..a6646f8
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestClass.c
@@ -0,0 +1,158 @@
+/* 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_BOOLEAN
+#define C_CFISH_CLASS
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "charmony.h"
+
+#include <string.h>
+
+#include "Clownfish/Test/TestClass.h"
+
+#include "Clownfish/Boolean.h"
+#include "Clownfish/Class.h"
+#include "Clownfish/Method.h"
+#include "Clownfish/String.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/Util/Memory.h"
+#include "Clownfish/Vector.h"
+
+TestClass*
+TestClass_new() {
+ return (TestClass*)Class_Make_Obj(TESTCLASS);
+}
+
+#if DEBUG_CLASS_CONTENTS
+
+#include <stdio.h>
+
+static void
+S_memdump(void *vptr, size_t size) {
+ unsigned char *ptr = (unsigned char*)vptr;
+ for (size_t i = 0; i < size; i++) {
+ printf("%02X ", ptr[i]);
+ }
+ printf("\n");
+}
+
+#endif /* DEBUG_CLASS_CONTENTS */
+
+static void
+test_bootstrap_idempotence(TestBatchRunner *runner) {
+ Class *bool_class = BOOLEAN;
+ uint32_t bool_class_size = BOOLEAN->class_alloc_size;
+ uint32_t bool_ivars_offset = cfish_Bool_IVARS_OFFSET;
+ Boolean *true_singleton = Bool_true_singleton;
+
+ char *bool_class_contents = (char*)MALLOCATE(bool_class_size);
+ memcpy(bool_class_contents, BOOLEAN, bool_class_size);
+
+ // Force another bootstrap run.
+ cfish_bootstrap_internal(1);
+
+#if DEBUG_CLASS_CONTENTS
+ printf("Before\n");
+ S_memdump(bool_class_contents, bool_class_size);
+ printf("After\n");
+ S_memdump(BOOLEAN, bool_class_size);
+#endif
+
+ TEST_TRUE(runner, bool_class == BOOLEAN,
+ "Boolean class pointer unchanged");
+ TEST_TRUE(runner,
+ memcmp(bool_class_contents, BOOLEAN, bool_class_size) == 0,
+ "Boolean class unchanged");
+ TEST_TRUE(runner, bool_ivars_offset == cfish_Bool_IVARS_OFFSET,
+ "Boolean ivars offset unchanged");
+ TEST_TRUE(runner, true_singleton == Bool_true_singleton,
+ "Boolean singleton unchanged");
+
+ FREEMEM(bool_class_contents);
+}
+
+static String*
+MyObj_To_String_IMP(Obj *self) {
+ UNUSED_VAR(self);
+ return Str_newf("delta");
+}
+
+static void
+test_simple_subclass(TestBatchRunner *runner) {
+ String *class_name = SSTR_WRAP_C("Clownfish::Test::MyObj");
+ Class *subclass = Class_singleton(class_name, OBJ);
+
+ TEST_TRUE(runner, Str_Equals(Class_Get_Name(subclass), (Obj*)class_name),
+ "Get_Name");
+ TEST_TRUE(runner, Class_Get_Parent(subclass) == OBJ, "Get_Parent");
+
+ Obj *obj = Class_Make_Obj(subclass);
+ TEST_TRUE(runner, Obj_is_a(obj, subclass), "Make_Obj");
+
+ Class_Override(subclass, (cfish_method_t)MyObj_To_String_IMP,
+ CFISH_Obj_To_String_OFFSET);
+ String *str = Obj_To_String(obj);
+ TEST_TRUE(runner, Str_Equals_Utf8(str, "delta", 5), "Override");
+ DECREF(str);
+
+ DECREF(obj);
+}
+
+static void
+test_add_alias_to_registry(TestBatchRunner *runner) {
+ static const char alias[] = "Clownfish::Test::ObjAlias";
+ bool added;
+
+ added = Class_add_alias_to_registry(OBJ, alias, sizeof(alias) - 1);
+ TEST_TRUE(runner, added, "add_alias_to_registry returns true");
+ Class *klass = Class_fetch_class(SSTR_WRAP_C(alias));
+ TEST_TRUE(runner, klass == OBJ, "add_alias_to_registry works");
+
+ added = Class_add_alias_to_registry(CLASS, alias, sizeof(alias) - 1);
+ TEST_FALSE(runner, added, "add_alias_to_registry returns false");
+}
+
+static void
+test_Get_Methods(TestBatchRunner *runner) {
+ Vector *methods = Class_Get_Methods(OBJ);
+ Method *destroy = NULL;
+
+ for (size_t i = 0, size = Vec_Get_Size(methods); i < size; i++) {
+ Method *method = (Method*)Vec_Fetch(methods, i);
+
+ if (Str_Equals_Utf8(Method_Get_Name(method), "Destroy", 7)) {
+ destroy = method;
+ }
+ }
+
+ TEST_TRUE(runner, destroy != NULL, "Destroy method found");
+
+ DECREF(methods);
+}
+
+void
+TestClass_Run_IMP(TestClass *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 12);
+ test_bootstrap_idempotence(runner);
+ test_simple_subclass(runner);
+ test_add_alias_to_registry(runner);
+ test_Get_Methods(runner);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestClass.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestClass.cfh b/runtime/test/Clownfish/Test/TestClass.cfh
new file mode 100644
index 0000000..615c34e
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestClass.cfh
@@ -0,0 +1,28 @@
+/* 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::TestClass
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestClass*
+ new();
+
+ void
+ Run(TestClass *self, TestBatchRunner *runner);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestErr.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestErr.c b/runtime/test/Clownfish/Test/TestErr.c
new file mode 100644
index 0000000..46ecb1e
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestErr.c
@@ -0,0 +1,193 @@
+/* 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/String.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Class.h"
+
+TestErr*
+TestErr_new() {
+ return (TestErr*)Class_Make_Obj(TESTERR);
+}
+
+static void
+test_To_String(TestBatchRunner *runner) {
+ String *message = Str_newf("oops");
+ Err *error = Err_new(message);
+ String *string = Err_To_String(error);
+ TEST_TRUE(runner, Str_Equals(message, (Obj*)string),
+ "Stringifies as message");
+ DECREF(string);
+ DECREF(error);
+}
+
+static void
+test_Cat_Mess(TestBatchRunner *runner) {
+ Err *error = Err_new(Str_newf("alpha"));
+ Err_Cat_Mess(error, SSTR_WRAP_C("\nbeta"));
+ String *mess = Err_Get_Mess(error);
+ TEST_TRUE(runner, Str_Equals_Utf8(mess, "alpha\nbeta", 10), "Cat_Mess");
+ DECREF(error);
+}
+
+static void
+test_Add_Frame(TestBatchRunner *runner) {
+ {
+ Err *error = Err_new(Str_newf("alpha"));
+ Err_Add_Frame(error, "source.c", 128, "function");
+ String *mess = Err_Get_Mess(error);
+ const char *expected = "alpha\n\tfunction at source.c line 128\n";
+ TEST_TRUE(runner, Str_Equals_Utf8(mess, expected, strlen(expected)),
+ "Add_Frame");
+ DECREF(error);
+ }
+
+ {
+ Err *error = Err_new(Str_newf("alpha\n"));
+ Err_Add_Frame(error, "source.c", 128, "function");
+ String *mess = Err_Get_Mess(error);
+ const char *expected = "alpha\n\tfunction at source.c line 128\n";
+ TEST_TRUE(runner, Str_Equals_Utf8(mess, expected, strlen(expected)),
+ "Add_Frame with trailing newline");
+ DECREF(error);
+ }
+
+ {
+ Err *error = Err_new(Str_newf("alpha"));
+ Err_Add_Frame(error, "source.c", 128, NULL);
+ String *mess = Err_Get_Mess(error);
+ const char *expected = "alpha\n\tat source.c line 128\n";
+ TEST_TRUE(runner, Str_Equals_Utf8(mess, expected, strlen(expected)),
+ "Add_Frame without func");
+ DECREF(error);
+ }
+}
+
+static void
+S_rethrow(void *context) {
+ Err *error = (Err*)context;
+ Err_rethrow(error, "src.c", 12, "fn");
+}
+
+static void
+test_rethrow(TestBatchRunner *runner) {
+ Err *error = Err_new(Str_newf("error"));
+ Err *rethrown = Err_trap(S_rethrow, error);
+ String *mess = Err_Get_Mess(rethrown);
+ const char *expected = "error\n\tfn at src.c line 12\n";
+ TEST_TRUE(runner, Str_Starts_With_Utf8(mess, expected, strlen(expected)),
+ "rethrow");
+ DECREF(error);
+}
+
+static void
+S_invalid_downcast(void *context) {
+ Obj *obj = (Obj*)context;
+ DOWNCAST(obj, ERR);
+}
+
+static void
+test_downcast(TestBatchRunner *runner) {
+ Obj *obj = (Obj*)Str_newf("gamma");
+
+ TEST_TRUE(runner, DOWNCAST(obj, STRING) != NULL, "downcast");
+
+ TEST_TRUE(runner, DOWNCAST(NULL, STRING) == NULL, "downcast NULL");
+
+ Err *error = Err_trap(S_invalid_downcast, obj);
+ TEST_TRUE(runner, error != NULL, "downcast throws");
+ DECREF(error);
+
+ DECREF(obj);
+}
+
+static void
+S_invalid_certify(void *context) {
+ Obj *obj = (Obj*)context;
+ CERTIFY(obj, ERR);
+}
+
+static void
+test_certify(TestBatchRunner *runner) {
+ Obj *obj = (Obj*)Str_newf("epsilon");
+ Err *error;
+
+ TEST_TRUE(runner, CERTIFY(obj, STRING) != NULL, "certify");
+
+ error = Err_trap(S_invalid_certify, NULL);
+ TEST_TRUE(runner, error != NULL, "certify NULL");
+ DECREF(error);
+
+ error = Err_trap(S_invalid_certify, obj);
+ TEST_TRUE(runner, error != NULL, "certify throws");
+ DECREF(error);
+
+ DECREF(obj);
+}
+
+static void
+S_err_thread(void *arg) {
+ TestBatchRunner *runner = (TestBatchRunner*)arg;
+
+ TEST_TRUE(runner, Err_get_error() == NULL,
+ "global error in thread initialized to null");
+
+ Err_set_error(Err_new(Str_newf("thread")));
+ String *mess = Err_Get_Mess(Err_get_error());
+ TEST_TRUE(runner, Str_Equals_Utf8(mess, "thread", 6),
+ "set_error in thread works");
+}
+
+static void
+test_threads(TestBatchRunner *runner) {
+ if (!TestUtils_has_threads) {
+ SKIP(runner, 3, "no thread support");
+ return;
+ }
+
+ Err_set_error(Err_new(Str_newf("main")));
+
+ void *runtime = TestUtils_clone_host_runtime();
+ Thread *thread = TestUtils_thread_create(S_err_thread, runner, runtime);
+ TestUtils_thread_join(thread);
+ TestUtils_destroy_host_runtime(runtime);
+
+ String *mess = Err_Get_Mess(Err_get_error());
+ TEST_TRUE(runner, Str_Equals_Utf8(mess, "main", 4),
+ "thread doesn't clobber global error");
+}
+
+void
+TestErr_Run_IMP(TestErr *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 15);
+ test_To_String(runner);
+ test_Cat_Mess(runner);
+ test_Add_Frame(runner);
+ test_rethrow(runner);
+ test_downcast(runner);
+ test_certify(runner);
+ test_threads(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestErr.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestErr.cfh b/runtime/test/Clownfish/Test/TestErr.cfh
new file mode 100644
index 0000000..178017c
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestErr.cfh
@@ -0,0 +1,28 @@
+/* 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::TestHarness::TestBatch {
+
+ inert incremented TestErr*
+ new();
+
+ void
+ Run(TestErr *self, TestBatchRunner *runner);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestHash.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestHash.c b/runtime/test/Clownfish/Test/TestHash.c
new file mode 100644
index 0000000..b00d891
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestHash.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.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+#define C_CFISH_HASH
+
+#include "Clownfish/Test/TestHash.h"
+
+#include "Clownfish/String.h"
+#include "Clownfish/Boolean.h"
+#include "Clownfish/Hash.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Vector.h"
+#include "Clownfish/Class.h"
+
+TestHash*
+TestHash_new() {
+ return (TestHash*)Class_Make_Obj(TESTHASH);
+}
+
+static void
+test_Equals(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(0);
+ Hash *other = Hash_new(0);
+ String *stuff = SSTR_WRAP_C("stuff");
+
+ TEST_TRUE(runner, Hash_Equals(hash, (Obj*)other),
+ "Empty hashes are equal");
+
+ Hash_Store_Utf8(hash, "foo", 3, (Obj*)CFISH_TRUE);
+ TEST_FALSE(runner, Hash_Equals(hash, (Obj*)other),
+ "Add one pair and Equals returns false");
+
+ Hash_Store_Utf8(other, "foo", 3, (Obj*)CFISH_TRUE);
+ TEST_TRUE(runner, Hash_Equals(hash, (Obj*)other),
+ "Add a matching pair and Equals returns true");
+
+ Hash_Store_Utf8(other, "foo", 3, INCREF(stuff));
+ TEST_FALSE(runner, Hash_Equals(hash, (Obj*)other),
+ "Non-matching value spoils Equals");
+
+ DECREF(hash);
+ DECREF(other);
+}
+
+static void
+test_Store_and_Fetch(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(100);
+ Hash *dupe = Hash_new(100);
+ const size_t starting_cap = Hash_Get_Capacity(hash);
+ Vector *expected = Vec_new(100);
+ Vector *got = Vec_new(100);
+ String *twenty = SSTR_WRAP_C("20");
+ String *forty = SSTR_WRAP_C("40");
+ String *foo = SSTR_WRAP_C("foo");
+
+ for (int32_t i = 0; i < 100; i++) {
+ String *str = Str_newf("%i32", i);
+ Hash_Store(hash, str, (Obj*)str);
+ Hash_Store(dupe, str, INCREF(str));
+ Vec_Push(expected, INCREF(str));
+ }
+ TEST_TRUE(runner, Hash_Equals(hash, (Obj*)dupe), "Equals");
+
+ TEST_UINT_EQ(runner, Hash_Get_Capacity(hash), starting_cap,
+ "Initial capacity sufficient (no rebuilds)");
+
+ for (size_t i = 0; i < 100; i++) {
+ String *key = (String*)Vec_Fetch(expected, i);
+ Obj *elem = Hash_Fetch(hash, key);
+ Vec_Push(got, (Obj*)INCREF(elem));
+ }
+
+ TEST_TRUE(runner, Vec_Equals(got, (Obj*)expected),
+ "basic Store and Fetch");
+ TEST_UINT_EQ(runner, Hash_Get_Size(hash), 100,
+ "size incremented properly by Hash_Store");
+
+ TEST_TRUE(runner, Hash_Fetch(hash, foo) == NULL,
+ "Fetch against non-existent key returns NULL");
+
+ String *twelve = (String*)Hash_Fetch_Utf8(hash, "12", 2);
+ TEST_TRUE(runner, Str_Equals_Utf8(twelve, "12", 2), "Fetch_Utf8");
+
+ Obj *stored_foo = INCREF(foo);
+ Hash_Store(hash, forty, stored_foo);
+ TEST_TRUE(runner, Str_Equals(foo, Hash_Fetch(hash, forty)),
+ "Hash_Store replaces existing value");
+ TEST_FALSE(runner, Hash_Equals(hash, (Obj*)dupe),
+ "replacement value spoils equals");
+ TEST_UINT_EQ(runner, Hash_Get_Size(hash), 100,
+ "size unaffected after value replaced");
+
+ TEST_TRUE(runner, Hash_Delete(hash, forty) == stored_foo,
+ "Delete returns value");
+ DECREF(stored_foo);
+ TEST_UINT_EQ(runner, Hash_Get_Size(hash), 99,
+ "size decremented by successful Delete");
+ TEST_TRUE(runner, Hash_Delete(hash, forty) == NULL,
+ "Delete returns NULL when key not found");
+ TEST_UINT_EQ(runner, Hash_Get_Size(hash), 99,
+ "size not decremented by unsuccessful Delete");
+ DECREF(Hash_Delete(dupe, forty));
+ TEST_TRUE(runner, Vec_Equals(got, (Obj*)expected), "Equals after Delete");
+
+ Obj *forty_one = Hash_Delete_Utf8(hash, "41", 2);
+ TEST_TRUE(runner, forty_one != NULL, "Delete_Utf8");
+ TEST_UINT_EQ(runner, Hash_Get_Size(hash), 98,
+ "Delete_Utf8 decrements size");
+ DECREF(forty_one);
+
+ Hash_Clear(hash);
+ TEST_TRUE(runner, Hash_Fetch(hash, twenty) == NULL, "Clear");
+ TEST_TRUE(runner, Hash_Get_Size(hash) == 0, "size is 0 after Clear");
+
+ Hash_Clear(hash);
+ Hash_Store(hash, forty, NULL);
+ TEST_TRUE(runner, Hash_Fetch(hash, forty) == NULL, "Store NULL");
+ TEST_TRUE(runner, Hash_Get_Size(hash) == 1, "Size after Store NULL");
+ TEST_TRUE(runner, Hash_Delete(hash, forty) == NULL, "Delete NULL value");
+ TEST_TRUE(runner, Hash_Get_Size(hash) == 0,
+ "Size after Deleting NULL val");
+
+ DECREF(hash);
+ DECREF(dupe);
+ DECREF(got);
+ DECREF(expected);
+}
+
+static void
+test_Keys_Values(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(0); // trigger multiple rebuilds.
+ Vector *expected = Vec_new(100);
+ Vector *keys;
+ Vector *values;
+
+ for (uint32_t i = 0; i < 500; i++) {
+ String *str = Str_newf("%u32", i);
+ Hash_Store(hash, str, (Obj*)str);
+ Vec_Push(expected, INCREF(str));
+ }
+
+ Vec_Sort(expected);
+
+ keys = Hash_Keys(hash);
+ values = Hash_Values(hash);
+ Vec_Sort(keys);
+ Vec_Sort(values);
+ TEST_TRUE(runner, Vec_Equals(keys, (Obj*)expected), "Keys");
+ TEST_TRUE(runner, Vec_Equals(values, (Obj*)expected), "Values");
+ Vec_Clear(keys);
+ Vec_Clear(values);
+
+ {
+ String *forty = SSTR_WRAP_C("40");
+ String *nope = SSTR_WRAP_C("nope");
+ TEST_TRUE(runner, Hash_Has_Key(hash, forty), "Has_Key");
+ TEST_FALSE(runner, Hash_Has_Key(hash, nope),
+ "Has_Key returns false for non-existent key");
+ }
+
+ DECREF(hash);
+ DECREF(expected);
+ DECREF(keys);
+ DECREF(values);
+}
+
+static void
+test_stress(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(0); // trigger multiple rebuilds.
+ Vector *expected = Vec_new(1000);
+ Vector *keys;
+ Vector *values;
+
+ for (uint32_t i = 0; i < 1000; i++) {
+ String *str = TestUtils_random_string((size_t)(rand() % 1200));
+ while (Hash_Fetch(hash, str)) {
+ DECREF(str);
+ str = TestUtils_random_string((size_t)(rand() % 1200));
+ }
+ Hash_Store(hash, str, (Obj*)str);
+ Vec_Push(expected, INCREF(str));
+ }
+
+ Vec_Sort(expected);
+
+ // Overwrite for good measure.
+ for (uint32_t i = 0; i < 1000; i++) {
+ String *str = (String*)Vec_Fetch(expected, i);
+ Hash_Store(hash, str, INCREF(str));
+ }
+
+ keys = Hash_Keys(hash);
+ values = Hash_Values(hash);
+ Vec_Sort(keys);
+ Vec_Sort(values);
+ TEST_TRUE(runner, Vec_Equals(keys, (Obj*)expected), "stress Keys");
+ TEST_TRUE(runner, Vec_Equals(values, (Obj*)expected), "stress Values");
+
+ DECREF(keys);
+ DECREF(values);
+ DECREF(expected);
+ DECREF(hash);
+}
+
+static void
+test_collision(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(0);
+ String *one = Str_newf("A");
+ String *two = Str_newf("P{2}|=~-ULE/d");
+
+ TEST_TRUE(runner, Str_Hash_Sum(one) == Str_Hash_Sum(two),
+ "Keys have the same hash sum");
+
+ Hash_Store(hash, one, INCREF(one));
+ Hash_Store(hash, two, INCREF(two));
+ String *elem = (String*)Hash_Fetch(hash, two);
+ TEST_TRUE(runner, elem == two, "Fetch works with collisions");
+
+ DECREF(one);
+ DECREF(two);
+ DECREF(hash);
+}
+
+static void
+test_store_skips_tombstone(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(0);
+ size_t mask = Hash_Get_Capacity(hash) - 1;
+
+ String *one = Str_newf("one");
+ size_t slot = Str_Hash_Sum(one) & mask;
+
+ // Find a colliding key.
+ String *two = NULL;
+ for (int i = 0; i < 100000; i++) {
+ two = Str_newf("%i32", i);
+ if (slot == (Str_Hash_Sum(two) & mask)) {
+ break;
+ }
+ DECREF(two);
+ two = NULL;
+ }
+
+ Hash_Store(hash, one, (Obj*)CFISH_TRUE);
+ Hash_Store(hash, two, (Obj*)CFISH_TRUE);
+ Hash_Delete(hash, one);
+ Hash_Store(hash, two, (Obj*)CFISH_TRUE);
+
+ TEST_UINT_EQ(runner, Hash_Get_Size(hash), 1, "Store skips tombstone");
+
+ DECREF(one);
+ DECREF(two);
+ DECREF(hash);
+}
+
+static void
+test_threshold_accounting(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(20);
+ String *key = Str_newf("key");
+
+ size_t threshold = hash->threshold;
+ Hash_Store(hash, key, (Obj*)CFISH_TRUE);
+ Hash_Delete(hash, key);
+ TEST_UINT_EQ(runner, hash->threshold, threshold - 1,
+ "Tombstone creation decreases threshold");
+
+ Hash_Store(hash, key, (Obj*)CFISH_TRUE);
+ TEST_UINT_EQ(runner, hash->threshold, threshold,
+ "Tombstone destruction increases threshold");
+
+ DECREF(key);
+ DECREF(hash);
+}
+
+static void
+test_tombstone_identification(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(20);
+ String *key = Str_newf("P{2}|=~-U@!y>");
+
+ // Tombstones have a zero hash_sum.
+ TEST_UINT_EQ(runner, Str_Hash_Sum(key), 0, "Key has zero hash sum");
+
+ Hash_Store(hash, key, (Obj*)CFISH_TRUE);
+ Hash_Delete(hash, key);
+ TEST_TRUE(runner, Hash_Fetch(hash, key) == NULL,
+ "Key with zero hash sum isn't mistaken for tombstone");
+
+ DECREF(key);
+ DECREF(hash);
+}
+
+void
+TestHash_Run_IMP(TestHash *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 39);
+ srand((unsigned int)time((time_t*)NULL));
+ test_Equals(runner);
+ test_Store_and_Fetch(runner);
+ test_Keys_Values(runner);
+ test_stress(runner);
+ test_collision(runner);
+ test_store_skips_tombstone(runner);
+ test_threshold_accounting(runner);
+ test_tombstone_identification(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestHash.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestHash.cfh b/runtime/test/Clownfish/Test/TestHash.cfh
new file mode 100644
index 0000000..a730105
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestHash.cfh
@@ -0,0 +1,29 @@
+/* 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::TestHarness::TestBatch {
+
+ inert incremented TestHash*
+ new();
+
+ void
+ Run(TestHash *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestHashIterator.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestHashIterator.c b/runtime/test/Clownfish/Test/TestHashIterator.c
new file mode 100644
index 0000000..fac7d69
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestHashIterator.c
@@ -0,0 +1,253 @@
+/* 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/TestHashIterator.h"
+
+#include "Clownfish/Err.h"
+#include "Clownfish/String.h"
+#include "Clownfish/Hash.h"
+#include "Clownfish/HashIterator.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/Vector.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Class.h"
+
+TestHashIterator*
+TestHashIterator_new() {
+ return (TestHashIterator*)Class_Make_Obj(TESTHASHITERATOR);
+}
+
+static void
+test_Next(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(0); // trigger multiple rebuilds.
+ Vector *expected = Vec_new(100);
+ Vector *keys = Vec_new(500);
+ Vector *values = Vec_new(500);
+
+ for (uint32_t i = 0; i < 500; i++) {
+ String *str = Str_newf("%u32", i);
+ Hash_Store(hash, str, (Obj*)str);
+ Vec_Push(expected, INCREF(str));
+ }
+
+ Vec_Sort(expected);
+
+ {
+ HashIterator *iter = HashIter_new(hash);
+ while (HashIter_Next(iter)) {
+ String *key = HashIter_Get_Key(iter);
+ Obj *value = HashIter_Get_Value(iter);
+ Vec_Push(keys, INCREF(key));
+ Vec_Push(values, INCREF(value));
+ }
+ TEST_TRUE(runner, !HashIter_Next(iter),
+ "Next continues to return false after iteration finishes.");
+
+ DECREF(iter);
+ }
+
+ Vec_Sort(keys);
+ Vec_Sort(values);
+ TEST_TRUE(runner, Vec_Equals(keys, (Obj*)expected), "Keys from Iter");
+ TEST_TRUE(runner, Vec_Equals(values, (Obj*)expected), "Values from Iter");
+
+ DECREF(hash);
+ DECREF(expected);
+ DECREF(keys);
+ DECREF(values);
+}
+
+static void
+S_invoke_Next(void *context) {
+ HashIterator *iter = (HashIterator*)context;
+ HashIter_Next(iter);
+}
+
+static void
+S_invoke_Get_Key(void *context) {
+ HashIterator *iter = (HashIterator*)context;
+ HashIter_Get_Key(iter);
+}
+
+static void
+S_invoke_Get_Value(void *context) {
+ HashIterator *iter = (HashIterator*)context;
+ HashIter_Get_Value(iter);
+}
+
+static void
+test_empty(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(0);
+ HashIterator *iter = HashIter_new(hash);
+
+ TEST_TRUE(runner, !HashIter_Next(iter),
+ "First call to next false on empty hash iteration");
+
+ Err *get_key_error = Err_trap(S_invoke_Get_Key, iter);
+ TEST_TRUE(runner, get_key_error != NULL,
+ "Get_Key throws exception on empty hash.");
+ DECREF(get_key_error);
+
+ Err *get_value_error = Err_trap(S_invoke_Get_Value, iter);
+ TEST_TRUE(runner, get_value_error != NULL,
+ "Get_Value throws exception on empty hash.");
+ DECREF(get_value_error);
+
+ DECREF(hash);
+ DECREF(iter);
+}
+
+static void
+test_Get_Key_and_Get_Value(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(0);
+ String *str = Str_newf("foo");
+ Hash_Store(hash, str, (Obj*)str);
+ bool ok;
+
+ HashIterator *iter = HashIter_new(hash);
+ DECREF(hash);
+
+ Err *get_key_error = Err_trap(S_invoke_Get_Key, iter);
+ TEST_TRUE(runner, get_key_error != NULL,
+ "Get_Key throws exception before first call to Next.");
+ ok = Str_Contains_Utf8(Err_Get_Mess(get_key_error), "before", 6);
+ TEST_TRUE(runner, ok, "Get_Key before Next throws correct message");
+ DECREF(get_key_error);
+
+ Err *get_value_error = Err_trap(S_invoke_Get_Value, iter);
+ TEST_TRUE(runner, get_value_error != NULL,
+ "Get_Value throws exception before first call to Next.");
+ ok = Str_Contains_Utf8(Err_Get_Mess(get_value_error), "before", 6);
+ TEST_TRUE(runner, ok, "Get_Value before Next throws correct message");
+ DECREF(get_value_error);
+
+ HashIter_Next(iter);
+ TEST_TRUE(runner, HashIter_Get_Key(iter) != NULL,
+ "Get_Key during iteration.");
+ TEST_TRUE(runner, HashIter_Get_Value(iter) != NULL,
+ "Get_Value during iteration.");
+
+ HashIter_Next(iter);
+ get_key_error = Err_trap(S_invoke_Get_Key, iter);
+ TEST_TRUE(runner, get_key_error != NULL,
+ "Get_Key throws exception after end of iteration.");
+ ok = Str_Contains_Utf8(Err_Get_Mess(get_key_error), "after", 5);
+ TEST_TRUE(runner, ok, "Get_Key after end throws correct message");
+ DECREF(get_key_error);
+
+ get_value_error = Err_trap(S_invoke_Get_Value, iter);
+ TEST_TRUE(runner, get_value_error != NULL,
+ "Get_Value throws exception after end of iteration.");
+ ok = Str_Contains_Utf8(Err_Get_Mess(get_value_error), "after", 5);
+ TEST_TRUE(runner, ok, "Get_Value after end throws correct message");
+ DECREF(get_value_error);
+
+
+ DECREF(iter);
+}
+
+static void
+test_illegal_modification(TestBatchRunner *runner) {
+ Hash *hash = Hash_new(0);
+
+ for (uint32_t i = 0; i < 3; i++) {
+ String *str = Str_newf("%u32", i);
+ Hash_Store(hash, str, (Obj*)str);
+ }
+
+ HashIterator *iter = HashIter_new(hash);
+ HashIter_Next(iter);
+
+ for (uint32_t i = 0; i < 100; i++) {
+ String *str = Str_newf("foo %u32", i);
+ Hash_Store(hash, str, (Obj*)str);
+ }
+
+ Err *next_error = Err_trap(S_invoke_Next, iter);
+ TEST_TRUE(runner, next_error != NULL,
+ "Next on resized hash throws exception.");
+ DECREF(next_error);
+
+ Err *get_key_error = Err_trap(S_invoke_Get_Key, iter);
+ TEST_TRUE(runner, get_key_error != NULL,
+ "Get_Key on resized hash throws exception.");
+ DECREF(get_key_error);
+
+ Err *get_value_error = Err_trap(S_invoke_Get_Value, iter);
+ TEST_TRUE(runner, get_value_error != NULL,
+ "Get_Value on resized hash throws exception.");
+ DECREF(get_value_error);
+
+ DECREF(hash);
+ DECREF(iter);
+}
+
+static void
+test_tombstone(TestBatchRunner *runner) {
+ {
+ Hash *hash = Hash_new(0);
+ String *str = Str_newf("foo");
+ Hash_Store(hash, str, INCREF(str));
+ DECREF(Hash_Delete(hash, str));
+ DECREF(str);
+
+ HashIterator *iter = HashIter_new(hash);
+ TEST_TRUE(runner, !HashIter_Next(iter), "Next advances past tombstones.");
+
+ DECREF(iter);
+ DECREF(hash);
+ }
+
+ {
+ Hash *hash = Hash_new(0);
+ String *str = Str_newf("foo");
+ Hash_Store(hash, str, INCREF(str));
+
+ HashIterator *iter = HashIter_new(hash);
+ HashIter_Next(iter);
+ DECREF(Hash_Delete(hash, str));
+
+
+ Err *get_key_error = Err_trap(S_invoke_Get_Key, iter);
+ TEST_TRUE(runner, get_key_error != NULL,
+ "Get_Key doesn't return tombstone and throws error.");
+ DECREF(get_key_error);
+
+ DECREF(str);
+ DECREF(iter);
+ DECREF(hash);
+ }
+}
+
+void
+TestHashIterator_Run_IMP(TestHashIterator *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 21);
+ srand((unsigned int)time((time_t*)NULL));
+ test_Next(runner);
+ test_empty(runner);
+ test_Get_Key_and_Get_Value(runner);
+ test_illegal_modification(runner);
+ test_tombstone(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestHashIterator.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestHashIterator.cfh b/runtime/test/Clownfish/Test/TestHashIterator.cfh
new file mode 100644
index 0000000..4765f76
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestHashIterator.cfh
@@ -0,0 +1,29 @@
+/* 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::TestHashIterator
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestHashIterator*
+ new();
+
+ void
+ Run(TestHashIterator *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestHost.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestHost.c b/runtime/test/Clownfish/Test/TestHost.c
new file mode 100644
index 0000000..6da0efa
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestHost.c
@@ -0,0 +1,125 @@
+/* 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/TestHost.h"
+#include "Clownfish/Class.h"
+#include "Clownfish/String.h"
+
+TestHost*
+TestHost_new() {
+ return (TestHost*)Class_Make_Obj(TESTHOST);
+}
+
+Obj*
+TestHost_Test_Obj_Pos_Arg_IMP(TestHost *self, Obj *arg) {
+ UNUSED_VAR(self);
+ return arg;
+}
+
+Obj*
+TestHost_Test_Obj_Pos_Arg_Def_IMP(TestHost *self, Obj *arg) {
+ UNUSED_VAR(self);
+ return arg;
+}
+
+Obj*
+TestHost_Test_Obj_Label_Arg_IMP(TestHost *self, Obj *arg, bool unused) {
+ UNUSED_VAR(self);
+ UNUSED_VAR(unused);
+ return arg;
+}
+
+Obj*
+TestHost_Test_Obj_Label_Arg_Def_IMP(TestHost *self, Obj *arg, bool unused) {
+ UNUSED_VAR(self);
+ UNUSED_VAR(unused);
+ return arg;
+}
+
+int32_t
+TestHost_Test_Int32_Pos_Arg_IMP(TestHost *self, int32_t arg) {
+ UNUSED_VAR(self);
+ return arg;
+}
+
+int32_t
+TestHost_Test_Int32_Pos_Arg_Def_IMP(TestHost *self, int32_t arg) {
+ UNUSED_VAR(self);
+ return arg;
+}
+
+int32_t
+TestHost_Test_Int32_Label_Arg_IMP(TestHost *self, int32_t arg, bool unused) {
+ UNUSED_VAR(self);
+ UNUSED_VAR(unused);
+ return arg;
+}
+
+int32_t
+TestHost_Test_Int32_Label_Arg_Def_IMP(TestHost *self, int32_t arg,
+ bool unused) {
+ UNUSED_VAR(self);
+ UNUSED_VAR(unused);
+ return arg;
+}
+
+bool
+TestHost_Test_Bool_Pos_Arg_IMP(TestHost *self, bool arg) {
+ UNUSED_VAR(self);
+ return arg;
+}
+
+bool
+TestHost_Test_Bool_Pos_Arg_Def_IMP(TestHost *self, bool arg) {
+ UNUSED_VAR(self);
+ return arg;
+}
+
+bool
+TestHost_Test_Bool_Label_Arg_IMP(TestHost *self, bool arg, bool unused) {
+ UNUSED_VAR(self);
+ UNUSED_VAR(unused);
+ return arg;
+}
+
+bool
+TestHost_Test_Bool_Label_Arg_Def_IMP(TestHost *self, bool arg, bool unused) {
+ UNUSED_VAR(self);
+ UNUSED_VAR(unused);
+ return arg;
+}
+
+void
+TestHost_Invoke_Invalid_Callback_From_C_IMP(TestHost *self) {
+ TestHost_Invalid_Callback(self);
+}
+
+String*
+TestHost_Aliased_IMP(TestHost *self) {
+ UNUSED_VAR(self);
+ return Str_newf("C");
+}
+
+String*
+TestHost_Invoke_Aliased_From_C_IMP(TestHost *self) {
+ UNUSED_VAR(self);
+ return TestHost_Aliased(self);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestHost.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestHost.cfh b/runtime/test/Clownfish/Test/TestHost.cfh
new file mode 100644
index 0000000..92bc272
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestHost.cfh
@@ -0,0 +1,81 @@
+/* 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;
+
+/** Clownfish test suite.
+ */
+class Clownfish::Test::TestHost {
+ inert incremented TestHost*
+ new();
+
+ Obj*
+ Test_Obj_Pos_Arg(TestHost *self, Obj *arg);
+
+ Obj*
+ Test_Obj_Pos_Arg_Def(TestHost *self, nullable Obj *arg = NULL);
+
+ Obj*
+ Test_Obj_Label_Arg(TestHost *self, Obj *arg, bool unused = false);
+
+ Obj*
+ Test_Obj_Label_Arg_Def(TestHost *self, nullable Obj *arg = NULL,
+ bool unused = false);
+
+ int32_t
+ Test_Int32_Pos_Arg(TestHost *self, int32_t arg);
+
+ int32_t
+ Test_Int32_Pos_Arg_Def(TestHost *self, int32_t arg = 101);
+
+ int32_t
+ Test_Int32_Label_Arg(TestHost *self, int32_t arg, bool unused = false);
+
+ int32_t
+ Test_Int32_Label_Arg_Def(TestHost *self, int32_t arg = 101,
+ bool unused = false);
+
+ bool
+ Test_Bool_Pos_Arg(TestHost *self, bool arg);
+
+ bool
+ Test_Bool_Pos_Arg_Def(TestHost *self, bool arg = true);
+
+ bool
+ Test_Bool_Label_Arg(TestHost *self, bool arg, bool unused = false);
+
+ bool
+ Test_Bool_Label_Arg_Def(TestHost *self, bool arg = true,
+ bool unused = false);
+
+ /** A method that can't be overridden from the host language.
+ */
+ abstract void*
+ Invalid_Callback(TestHost *self);
+
+ void
+ Invoke_Invalid_Callback_From_C(TestHost *self);
+
+ /** A method with a custom host language alias.
+ */
+ incremented String*
+ Aliased(TestHost *self);
+
+ incremented String*
+ Invoke_Aliased_From_C(TestHost* self);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestLockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestLockFreeRegistry.c b/runtime/test/Clownfish/Test/TestLockFreeRegistry.c
new file mode 100644
index 0000000..b70ff1f
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestLockFreeRegistry.c
@@ -0,0 +1,168 @@
+/* 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 CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestLockFreeRegistry.h"
+
+#include "Clownfish/Class.h"
+#include "Clownfish/LockFreeRegistry.h"
+#include "Clownfish/String.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Util/Memory.h"
+
+#define NUM_THREADS 5
+
+typedef struct ThreadArgs {
+ LockFreeRegistry *registry;
+ uint32_t *nums;
+ uint32_t num_objs;
+ uint64_t target_time;
+ uint32_t succeeded;
+} ThreadArgs;
+
+TestLockFreeRegistry*
+TestLFReg_new() {
+ return (TestLockFreeRegistry*)Class_Make_Obj(TESTLOCKFREEREGISTRY);
+}
+
+static void
+test_all(TestBatchRunner *runner) {
+ LockFreeRegistry *registry = LFReg_new(1);
+ String *foo = Str_newf("foo");
+ String *bar = Str_newf("bar");
+ String *baz = Str_newf("baz");
+ String *foo_dupe = Str_newf("foo");
+
+ TEST_TRUE(runner, LFReg_register(registry, foo, (Obj*)foo),
+ "Register() returns true on success");
+ TEST_FALSE(runner,
+ LFReg_register(registry, foo_dupe, (Obj*)foo_dupe),
+ "Can't Register() keys that test equal");
+
+ TEST_TRUE(runner, LFReg_register(registry, bar, (Obj*)bar),
+ "Register() key with the same Hash_Sum but that isn't Equal");
+
+ TEST_TRUE(runner, LFReg_fetch(registry, foo_dupe) == (Obj*)foo,
+ "Fetch()");
+ TEST_TRUE(runner, LFReg_fetch(registry, bar) == (Obj*)bar,
+ "Fetch() again");
+ TEST_TRUE(runner, LFReg_fetch(registry, baz) == NULL,
+ "Fetch() non-existent key returns NULL");
+
+ DECREF(foo_dupe);
+ DECREF(baz);
+ DECREF(bar);
+ DECREF(foo);
+ LFReg_destroy(registry);
+}
+
+static void
+S_register_many(void *varg) {
+ ThreadArgs *args = (ThreadArgs*)varg;
+
+ // Encourage contention, so that all threads try to register at the same
+ // time.
+
+ // Sleep until target_time.
+ uint64_t time = TestUtils_time();
+ if (args->target_time > time) {
+ TestUtils_usleep(args->target_time - time);
+ }
+
+ TestUtils_thread_yield();
+
+ uint32_t succeeded = 0;
+ for (uint32_t i = 0; i < args->num_objs; i++) {
+ String *obj = Str_newf("%u32", args->nums[i]);
+ if (LFReg_register(args->registry, obj, (Obj*)obj)) {
+ succeeded++;
+ }
+ DECREF(obj);
+ }
+
+ args->succeeded = succeeded;
+}
+
+static void
+test_threads(TestBatchRunner *runner) {
+ if (!TestUtils_has_threads) {
+ SKIP(runner, 1, "No thread support");
+ return;
+ }
+
+ LockFreeRegistry *registry = LFReg_new(32);
+ ThreadArgs thread_args[NUM_THREADS];
+ uint32_t num_objs = 10000;
+
+ for (uint32_t i = 0; i < NUM_THREADS; i++) {
+ uint32_t *nums = (uint32_t*)MALLOCATE(num_objs * sizeof(uint32_t));
+
+ for (uint32_t j = 0; j < num_objs; j++) {
+ nums[j] = j;
+ }
+
+ // Fisher-Yates shuffle.
+ for (uint32_t j = num_objs - 1; j > 0; j--) {
+ uint32_t r = (uint32_t)TestUtils_random_u64() % (j + 1);
+ uint32_t tmp = nums[j];
+ nums[j] = nums[r];
+ nums[r] = tmp;
+ }
+
+ thread_args[i].registry = registry;
+ thread_args[i].nums = nums;
+ thread_args[i].num_objs = num_objs;
+ }
+
+ Thread *threads[NUM_THREADS];
+ uint64_t target_time = TestUtils_time() + 200 * 1000;
+
+ for (uint32_t i = 0; i < NUM_THREADS; i++) {
+ thread_args[i].target_time = target_time;
+ threads[i]
+ = TestUtils_thread_create(S_register_many, &thread_args[i], NULL);
+ }
+
+ uint32_t total_succeeded = 0;
+
+ for (uint32_t i = 0; i < NUM_THREADS; i++) {
+ TestUtils_thread_join(threads[i]);
+ total_succeeded += thread_args[i].succeeded;
+ FREEMEM(thread_args[i].nums);
+ }
+
+ TEST_INT_EQ(runner, total_succeeded, num_objs,
+ "registered exactly the right number of entries across all"
+ " threads");
+
+ LFReg_destroy(registry);
+}
+
+void
+TestLFReg_Run_IMP(TestLockFreeRegistry *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 7);
+ test_all(runner);
+ test_threads(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestLockFreeRegistry.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestLockFreeRegistry.cfh b/runtime/test/Clownfish/Test/TestLockFreeRegistry.cfh
new file mode 100644
index 0000000..784f745
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestLockFreeRegistry.cfh
@@ -0,0 +1,29 @@
+/* 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 nickname TestLFReg
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestLockFreeRegistry*
+ new();
+
+ void
+ Run(TestLockFreeRegistry *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestMethod.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestMethod.c b/runtime/test/Clownfish/Test/TestMethod.c
new file mode 100644
index 0000000..7c39759
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestMethod.c
@@ -0,0 +1,91 @@
+/* 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/TestMethod.h"
+
+#include "Clownfish/Err.h"
+#include "Clownfish/Method.h"
+#include "Clownfish/String.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+
+TestMethod*
+TestMethod_new() {
+ return (TestMethod*)Class_Make_Obj(TESTMETHOD);
+}
+
+static void
+S_set_host_alias(void *context) {
+ Method *method = (Method*)context;
+ Method_Set_Host_Alias(method, SSTR_WRAP_C("foo"));
+}
+
+static void
+test_accessors(TestBatchRunner *runner) {
+ String *name = SSTR_WRAP_C("Frobnicate_Widget");
+ Method *method = Method_new(name, NULL, 0);
+
+ TEST_TRUE(runner, Str_Equals(Method_Get_Name(method), (Obj*)name),
+ "Get_Name");
+
+ String *alias = SSTR_WRAP_C("host_frob");
+ Method_Set_Host_Alias(method, alias);
+ TEST_TRUE(runner, Str_Equals(Method_Get_Host_Alias(method), (Obj*)alias),
+ "Set_Host_Alias");
+ Err *error = Err_trap(S_set_host_alias, method);
+ TEST_TRUE(runner, error != NULL,
+ "Set_Host_Alias can't be called more than once");
+ DECREF(error);
+
+ TEST_FALSE(runner, Method_Is_Excluded_From_Host(method),
+ "Is_Excluded_From_Host");
+
+ Method_Destroy(method);
+}
+
+static void
+test_lower_snake_alias(TestBatchRunner *runner) {
+ String *name = SSTR_WRAP_C("Frobnicate_Widget");
+ Method *method = Method_new(name, NULL, 0);
+
+ {
+ String *alias = Method_lower_snake_alias(method);
+ TEST_TRUE(runner, Str_Equals_Utf8(alias, "frobnicate_widget", 17),
+ "lower_snake_alias without explicit alias");
+ DECREF(alias);
+ }
+
+ {
+ String *new_alias = SSTR_WRAP_C("host_frob");
+ Method_Set_Host_Alias(method, new_alias);
+ String *alias = Method_lower_snake_alias(method);
+ TEST_TRUE(runner, Str_Equals(alias, (Obj*)new_alias),
+ "lower_snake_alias with explicit alias");
+ DECREF(alias);
+ }
+
+ Method_Destroy(method);
+}
+
+void
+TestMethod_Run_IMP(TestMethod *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
+ test_accessors(runner);
+ test_lower_snake_alias(runner);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestMethod.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestMethod.cfh b/runtime/test/Clownfish/Test/TestMethod.cfh
new file mode 100644
index 0000000..76b9558
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestMethod.cfh
@@ -0,0 +1,28 @@
+/* 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::TestMethod
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestMethod*
+ new();
+
+ void
+ Run(TestMethod *self, TestBatchRunner *runner);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestNum.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestNum.c b/runtime/test/Clownfish/Test/TestNum.c
new file mode 100644
index 0000000..dfa6769
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestNum.c
@@ -0,0 +1,278 @@
+/* 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 <math.h>
+
+#include "charmony.h"
+
+#include "Clownfish/Test/TestNum.h"
+
+#include "Clownfish/Err.h"
+#include "Clownfish/String.h"
+#include "Clownfish/Num.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Class.h"
+
+TestNum*
+TestNum_new() {
+ return (TestNum*)Class_Make_Obj(TESTNUM);
+}
+
+static void
+test_To_String(TestBatchRunner *runner) {
+ Float *f64 = Float_new(1.33);
+ Integer *i64 = Int_new(INT64_MAX);
+ String *f64_string = Float_To_String(f64);
+ String *i64_string = Int_To_String(i64);
+
+ TEST_TRUE(runner, Str_Starts_With_Utf8(f64_string, "1.3", 3),
+ "Float_To_String");
+ TEST_TRUE(runner, Str_Equals_Utf8(i64_string, "9223372036854775807", 19),
+ "Int_To_String");
+
+ DECREF(i64_string);
+ DECREF(f64_string);
+ DECREF(i64);
+ DECREF(f64);
+}
+
+static void
+S_float_to_i64(void *context) {
+ Float *f = (Float*)context;
+ Float_To_I64(f);
+}
+
+static void
+test_accessors(TestBatchRunner *runner) {
+ Float *f64 = Float_new(1.33);
+ Integer *i64 = Int_new(INT64_MIN);
+ double wanted64 = 1.33;
+ double got64;
+
+ got64 = Float_Get_Value(f64);
+ TEST_TRUE(runner, *(int64_t*)&got64 == *(int64_t*)&wanted64,
+ "F64 Get_Value");
+ TEST_TRUE(runner, Float_To_I64(f64) == 1, "Float_To_I64");
+
+ {
+ Float *huge = Float_new(1e40);
+ Err *error = Err_trap(S_float_to_i64, huge);
+ TEST_TRUE(runner, error != NULL,
+ "Float_To_I64 throws when out of range (+)");
+ DECREF(error);
+ DECREF(huge);
+ }
+
+ {
+ Float *huge = Float_new(-1e40);
+ Err *error = Err_trap(S_float_to_i64, huge);
+ TEST_TRUE(runner, error != NULL,
+ "Float_To_I64 throws when out of range (-)");
+ DECREF(error);
+ DECREF(huge);
+ }
+
+ TEST_TRUE(runner, Int_Get_Value(i64) == INT64_MIN, "I64 Get_Value");
+ TEST_TRUE(runner, Int_To_F64(i64) == -9223372036854775808.0, "Int_To_F64");
+
+ DECREF(i64);
+ DECREF(f64);
+}
+
+static void
+S_test_compare_float_int(TestBatchRunner *runner, double f64_val,
+ int64_t i64_val, int32_t result) {
+ Float *f64;
+ Integer *i64;
+
+ f64 = Float_new(f64_val);
+ i64 = Int_new(i64_val);
+ TEST_INT_EQ(runner, Float_Compare_To(f64, (Obj*)i64), result,
+ "Float_Compare_To %f %" PRId64, f64_val, i64_val);
+ TEST_INT_EQ(runner, Int_Compare_To(i64, (Obj*)f64), -result,
+ "Int_Compare_To %" PRId64" %f", i64_val, f64_val);
+ TEST_INT_EQ(runner, Float_Equals(f64, (Obj*)i64), result == 0,
+ "Float_Equals %f %" PRId64, f64_val, i64_val);
+ TEST_INT_EQ(runner, Int_Equals(i64, (Obj*)f64), result == 0,
+ "Int_Equals %" PRId64 " %f", i64_val, f64_val);
+ DECREF(f64);
+ DECREF(i64);
+
+ if (i64_val == INT64_MIN) { return; }
+
+ f64 = Float_new(-f64_val);
+ i64 = Int_new(-i64_val);
+ TEST_INT_EQ(runner, Float_Compare_To(f64, (Obj*)i64), -result,
+ "Float_Compare_To %f %" PRId64, -f64_val, -i64_val);
+ TEST_INT_EQ(runner, Int_Compare_To(i64, (Obj*)f64), result,
+ "Int_Compare_To %" PRId64" %f", -i64_val, -f64_val);
+ TEST_INT_EQ(runner, Float_Equals(f64, (Obj*)i64), result == 0,
+ "Float_Equals %f %" PRId64, -f64_val, -i64_val);
+ TEST_INT_EQ(runner, Int_Equals(i64, (Obj*)f64), result == 0,
+ "Int_Equals %" PRId64 " %f", -i64_val, -f64_val);
+ DECREF(f64);
+ DECREF(i64);
+}
+
+static void
+S_float_compare_to(void *context) {
+ Float *f = (Float*)context;
+ Float_Compare_To(f, (Obj*)OBJ);
+}
+
+static void
+S_int_compare_to(void *context) {
+ Integer *i = (Integer*)context;
+ Int_Compare_To(i, (Obj*)OBJ);
+}
+
+static void
+test_Equals_and_Compare_To(TestBatchRunner *runner) {
+ {
+ Float *f1 = Float_new(1.0);
+ Float *f2 = Float_new(1.0);
+ TEST_TRUE(runner, Float_Compare_To(f1, (Obj*)f2) == 0,
+ "Float_Compare_To equal");
+ TEST_TRUE(runner, Float_Equals(f1, (Obj*)f2),
+ "Float_Equals equal");
+ DECREF(f1);
+ DECREF(f2);
+ }
+
+ {
+ Float *f1 = Float_new(1.0);
+ Float *f2 = Float_new(2.0);
+ TEST_TRUE(runner, Float_Compare_To(f1, (Obj*)f2) < 0,
+ "Float_Compare_To less than");
+ TEST_FALSE(runner, Float_Equals(f1, (Obj*)f2),
+ "Float_Equals less than");
+ DECREF(f1);
+ DECREF(f2);
+ }
+
+ {
+ Float *f1 = Float_new(1.0);
+ Float *f2 = Float_new(0.0);
+ TEST_TRUE(runner, Float_Compare_To(f1, (Obj*)f2) > 0,
+ "Float_Compare_To greater than");
+ TEST_FALSE(runner, Float_Equals(f1, (Obj*)f2),
+ "Float_Equals greater than");
+ DECREF(f1);
+ DECREF(f2);
+ }
+
+ {
+ Float *f = Float_new(1.0);
+ Err *error = Err_trap(S_float_compare_to, f);
+ TEST_TRUE(runner, error != NULL,
+ "Float_Compare_To with invalid type throws");
+ TEST_FALSE(runner, Float_Equals(f, (Obj*)OBJ),
+ "Float_Equals with different type");
+ DECREF(error);
+ DECREF(f);
+ }
+
+ {
+ Integer *i1 = Int_new(INT64_C(0x6666666666666666));
+ Integer *i2 = Int_new(INT64_C(0x6666666666666666));
+ TEST_TRUE(runner, Int_Compare_To(i1, (Obj*)i2) == 0,
+ "Int_Compare_To equal");
+ TEST_TRUE(runner, Int_Equals(i1, (Obj*)i2),
+ "Int_Equals equal");
+ DECREF(i1);
+ DECREF(i2);
+ }
+
+ {
+ Integer *i1 = Int_new(INT64_C(0x6666666666666666));
+ Integer *i2 = Int_new(INT64_C(0x6666666666666667));
+ TEST_TRUE(runner, Int_Compare_To(i1, (Obj*)i2) < 0,
+ "Int_Compare_To less than");
+ TEST_FALSE(runner, Int_Equals(i1, (Obj*)i2),
+ "Int_Equals less than");
+ DECREF(i1);
+ DECREF(i2);
+ }
+
+ {
+ Integer *i1 = Int_new(INT64_C(0x6666666666666666));
+ Integer *i2 = Int_new(INT64_C(0x6666666666666665));
+ TEST_TRUE(runner, Int_Compare_To(i1, (Obj*)i2) > 0,
+ "Int_Compare_To greater than");
+ TEST_FALSE(runner, Int_Equals(i1, (Obj*)i2),
+ "Int_Equals greater than");
+ DECREF(i1);
+ DECREF(i2);
+ }
+
+ {
+ Integer *i = Int_new(0);
+ Err *error = Err_trap(S_int_compare_to, i);
+ TEST_TRUE(runner, error != NULL,
+ "Int_Compare_To with invalid type throws");
+ TEST_FALSE(runner, Int_Equals(i, (Obj*)OBJ),
+ "Int_Equals with different type");
+ DECREF(error);
+ DECREF(i);
+ }
+
+ // NOTICE: When running these tests on x86/x64, it's best to compile
+ // with -ffloat-store to avoid excess FPU precision which can hide
+ // implementation bugs.
+ S_test_compare_float_int(runner, (double)INT64_MAX * 2.0, INT64_MAX, 1);
+ S_test_compare_float_int(runner, pow(2.0, 60.0), INT64_C(1) << 60, 0);
+ S_test_compare_float_int(runner, pow(2.0, 60.0), (INT64_C(1) << 60) - 1,
+ 1);
+ S_test_compare_float_int(runner, pow(2.0, 60.0), (INT64_C(1) << 60) + 1,
+ -1);
+ S_test_compare_float_int(runner, pow(2.0, 63.0), INT64_MAX, 1);
+ S_test_compare_float_int(runner, -pow(2.0, 63.0), INT64_MIN, 0);
+ // -9223372036854777856.0 == nextafter(-pow(2, 63), -INFINITY)
+ S_test_compare_float_int(runner, -9223372036854777856.0, INT64_MIN, -1);
+ S_test_compare_float_int(runner, 1.0, 2, -1);
+}
+
+static void
+test_Clone(TestBatchRunner *runner) {
+ Float *f64 = Float_new(1.33);
+ Integer *i64 = Int_new(INT64_MAX);
+ Float *f64_dupe = Float_Clone(f64);
+ Integer *i64_dupe = Int_Clone(i64);
+ TEST_TRUE(runner, Float_Equals(f64, (Obj*)f64_dupe),
+ "Float Clone");
+ TEST_TRUE(runner, Int_Equals(i64, (Obj*)i64_dupe),
+ "Integer Clone");
+ DECREF(i64_dupe);
+ DECREF(f64_dupe);
+ DECREF(i64);
+ DECREF(f64);
+}
+
+void
+TestNum_Run_IMP(TestNum *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 82);
+ test_To_String(runner);
+ test_accessors(runner);
+ test_Equals_and_Compare_To(runner);
+ test_Clone(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestNum.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestNum.cfh b/runtime/test/Clownfish/Test/TestNum.cfh
new file mode 100644
index 0000000..6d1f663
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestNum.cfh
@@ -0,0 +1,29 @@
+/* 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::TestHarness::TestBatch {
+
+ inert incremented TestNum*
+ new();
+
+ void
+ Run(TestNum *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestObj.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestObj.c b/runtime/test/Clownfish/Test/TestObj.c
new file mode 100644
index 0000000..c4cdafe
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestObj.c
@@ -0,0 +1,152 @@
+/* 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 CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "charmony.h"
+
+#include "Clownfish/Test/TestObj.h"
+
+#include "Clownfish/String.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/Class.h"
+
+TestObj*
+TestObj_new() {
+ return (TestObj*)Class_Make_Obj(TESTOBJ);
+}
+
+static Obj*
+S_new_testobj() {
+ String *class_name = SSTR_WRAP_C("TestObj");
+ Obj *obj;
+ Class *klass = Class_fetch_class(class_name);
+ if (!klass) {
+ klass = Class_singleton(class_name, OBJ);
+ }
+ obj = Class_Make_Obj(klass);
+ return Obj_init(obj);
+}
+
+static void
+test_refcounts(TestBatchRunner *runner) {
+ Obj *obj = S_new_testobj();
+
+ TEST_INT_EQ(runner, CFISH_REFCOUNT_NN(obj), 1,
+ "Correct starting refcount");
+
+ obj = CFISH_INCREF_NN(obj);
+ TEST_INT_EQ(runner, CFISH_REFCOUNT_NN(obj), 2, "INCREF_NN");
+
+ CFISH_DECREF_NN(obj);
+ TEST_INT_EQ(runner, CFISH_REFCOUNT_NN(obj), 1, "DECREF_NN");
+
+ DECREF(obj);
+}
+
+static void
+test_To_String(TestBatchRunner *runner) {
+ Obj *testobj = S_new_testobj();
+ String *string = Obj_To_String(testobj);
+ TEST_TRUE(runner, Str_Contains_Utf8(string, "TestObj", 7), "To_String");
+ DECREF(string);
+ DECREF(testobj);
+}
+
+static void
+test_Equals(TestBatchRunner *runner) {
+ Obj *testobj = S_new_testobj();
+ Obj *other = S_new_testobj();
+
+ TEST_TRUE(runner, Obj_Equals(testobj, testobj),
+ "Equals is true for the same object");
+ TEST_FALSE(runner, Obj_Equals(testobj, other),
+ "Distinct objects are not equal");
+
+ DECREF(testobj);
+ DECREF(other);
+}
+
+static void
+test_is_a(TestBatchRunner *runner) {
+ String *string = Str_new_from_trusted_utf8("", 0);
+ Class *str_class = Str_get_class(string);
+ String *class_name = Str_get_class_name(string);
+
+ TEST_TRUE(runner, Str_is_a(string, STRING), "String is_a String.");
+ TEST_TRUE(runner, Str_is_a(string, OBJ), "String is_a Obj.");
+ TEST_TRUE(runner, str_class == STRING, "get_class");
+ TEST_TRUE(runner, Str_Equals(Class_Get_Name(STRING), (Obj*)class_name),
+ "get_class_name");
+ TEST_FALSE(runner, Obj_is_a(NULL, OBJ), "NULL is not an Obj");
+
+ DECREF(string);
+}
+
+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_Compare_To(void *context) {
+ Obj_Compare_To((Obj*)context, (Obj*)context);
+}
+
+static void
+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(runner, error != NULL
+ && Err_is_a(error, ERR)
+ && Str_Contains_Utf8(Err_Get_Mess(error), "bstract", 7),
+ message);
+ DECREF(error);
+}
+
+static void
+test_abstract_routines(TestBatchRunner *runner) {
+ Obj *blank = Class_Make_Obj(OBJ);
+ S_verify_abstract_error(runner, S_attempt_init, blank, "init");
+
+ Obj *obj = S_new_testobj();
+ S_verify_abstract_error(runner, S_attempt_Clone, obj, "Clone");
+ S_verify_abstract_error(runner, S_attempt_Compare_To, obj, "Compare_To");
+ DECREF(obj);
+}
+
+void
+TestObj_Run_IMP(TestObj *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 14);
+ test_refcounts(runner);
+ test_To_String(runner);
+ test_Equals(runner);
+ test_is_a(runner);
+ test_abstract_routines(runner);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestObj.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestObj.cfh b/runtime/test/Clownfish/Test/TestObj.cfh
new file mode 100644
index 0000000..c5cc401
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestObj.cfh
@@ -0,0 +1,28 @@
+/* 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::TestHarness::TestBatch {
+
+ inert incremented TestObj*
+ new();
+
+ void
+ Run(TestObj *self, TestBatchRunner *runner);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestPtrHash.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestPtrHash.c b/runtime/test/Clownfish/Test/TestPtrHash.c
new file mode 100644
index 0000000..3bf7003
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestPtrHash.c
@@ -0,0 +1,108 @@
+/* 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 <stdlib.h>
+#include <time.h>
+
+#include "Clownfish/Test/TestPtrHash.h"
+#include "Clownfish/Class.h"
+#include "Clownfish/PtrHash.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Util/Memory.h"
+
+TestPtrHash*
+TestPtrHash_new() {
+ return (TestPtrHash*)Class_Make_Obj(TESTPTRHASH);
+}
+
+static void
+test_Store_and_Fetch(TestBatchRunner *runner) {
+ PtrHash *hash = PtrHash_new(100);
+ char dummy[100];
+
+ for (int i = 0; i < 100; i++) {
+ void *key = &dummy[i];
+ PtrHash_Store(hash, key, key);
+ }
+
+ bool all_equal = true;
+ for (int i = 0; i < 100; i++) {
+ void *key = &dummy[i];
+ void *value = PtrHash_Fetch(hash, key);
+ if (value != key) {
+ all_equal = false;
+ break;
+ }
+ }
+ TEST_TRUE(runner, all_equal, "basic Store and Fetch");
+
+ TEST_TRUE(runner, PtrHash_Fetch(hash, &dummy[100]) == NULL,
+ "Fetch against non-existent key returns NULL");
+
+ PtrHash_Store(hash, &dummy[50], dummy);
+ TEST_TRUE(runner, PtrHash_Fetch(hash, &dummy[50]) == dummy,
+ "Store replaces existing value");
+
+ PtrHash_Destroy(hash);
+}
+
+static void
+test_stress(TestBatchRunner *runner) {
+ PtrHash *hash = PtrHash_new(0); // trigger multiple rebuilds.
+ size_t num_elems = 200000;
+ void **keys = (void**)MALLOCATE(num_elems * sizeof(void*));
+
+ for (size_t i = 0; i < num_elems; i++) {
+ size_t index = (size_t)(TestUtils_random_u64() % num_elems);
+ void *key = &keys[index];
+ PtrHash_Store(hash, key, key);
+ keys[i] = key;
+ }
+
+ // Overwrite for good measure.
+ for (size_t i = 0; i < num_elems; i++) {
+ void *key = keys[i];
+ PtrHash_Store(hash, key, key);
+ }
+
+ bool all_equal = true;
+ for (size_t i = 0; i < num_elems; i++) {
+ void *key = keys[i];
+ void *got = PtrHash_Fetch(hash, key);
+ if (got != key) {
+ all_equal = false;
+ break;
+ }
+ }
+ TEST_TRUE(runner, all_equal, "stress test");
+
+ FREEMEM(keys);
+ PtrHash_Destroy(hash);
+}
+
+void
+TestPtrHash_Run_IMP(TestPtrHash *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 4);
+ srand((unsigned int)time(NULL));
+ test_Store_and_Fetch(runner);
+ test_stress(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestPtrHash.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestPtrHash.cfh b/runtime/test/Clownfish/Test/TestPtrHash.cfh
new file mode 100644
index 0000000..83589cb
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestPtrHash.cfh
@@ -0,0 +1,29 @@
+/* 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::TestPtrHash
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestPtrHash*
+ new();
+
+ void
+ Run(TestPtrHash *self, TestBatchRunner *runner);
+}
+
+
[04/14] lucy-clownfish git commit: Rename core directory to "cfcore"
for CPAN tarball
Posted by nw...@apache.org.
Rename core directory to "cfcore" for CPAN tarball
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/5bda4dad
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/5bda4dad
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/5bda4dad
Branch: refs/heads/master
Commit: 5bda4dadd15edf1cd9c0b1d171b99dcf935a6c68
Parents: 56f1982
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 8 13:57:06 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 8 14:25:36 2016 +0200
----------------------------------------------------------------------
compiler/perl/lib/Clownfish/CFC/Perl/Build.pm | 2 +-
runtime/perl/buildlib/Clownfish/Build.pm | 12 +++++++-----
2 files changed, 8 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5bda4dad/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
index 804ba87..6d0f584 100644
--- a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
+++ b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
@@ -48,7 +48,7 @@ else {
# development, the files are accessed from their original locations.
my @BASE_PATH;
-push(@BASE_PATH, updir()) unless -e 'core';
+push(@BASE_PATH, updir()) unless -d 'core' || -d 'cfcore';
my $AUTOGEN_DIR = 'autogen';
my $LIB_DIR = 'lib';
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5bda4dad/runtime/perl/buildlib/Clownfish/Build.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/buildlib/Clownfish/Build.pm b/runtime/perl/buildlib/Clownfish/Build.pm
index 3d1b8c3..9506662 100644
--- a/runtime/perl/buildlib/Clownfish/Build.pm
+++ b/runtime/perl/buildlib/Clownfish/Build.pm
@@ -21,7 +21,7 @@ package Clownfish::Build;
my $IS_CPAN_DIST;
BEGIN {
- $IS_CPAN_DIST = -e 'core';
+ $IS_CPAN_DIST = -e 'cfcore';
if (!$IS_CPAN_DIST) {
unshift @INC,
@@ -49,17 +49,19 @@ use Cwd qw( getcwd );
my @BASE_PATH = __PACKAGE__->cf_base_path;
my $COMMON_SOURCE_DIR = catdir( @BASE_PATH, 'common' );
-my $CORE_SOURCE_DIR = catdir( @BASE_PATH, 'core' );
my $CFC_DIR = catdir( @BASE_PATH, updir(), 'compiler', 'perl' );
my $XS_SOURCE_DIR = 'xs';
my $CFC_BUILD = catfile( $CFC_DIR, 'Build' );
my $LIB_DIR = 'lib';
+my $CORE_SOURCE_DIR;
my $CHARMONIZER_C;
if ($IS_CPAN_DIST) {
- $CHARMONIZER_C = 'charmonizer.c';
+ $CORE_SOURCE_DIR = 'cfcore';
+ $CHARMONIZER_C = 'charmonizer.c';
}
else {
- $CHARMONIZER_C = catfile( $COMMON_SOURCE_DIR, 'charmonizer.c' );
+ $CORE_SOURCE_DIR = catdir( @BASE_PATH, 'core' );
+ $CHARMONIZER_C = catfile( $COMMON_SOURCE_DIR, 'charmonizer.c' );
}
sub new {
@@ -314,7 +316,7 @@ sub ACTION_dist {
'../../LICENSE' => 'LICENSE',
'../../NOTICE' => 'NOTICE',
'../../README.md' => 'README.md',
- $CORE_SOURCE_DIR => 'core',
+ $CORE_SOURCE_DIR => 'cfcore',
$CHARMONIZER_C => 'charmonizer.c',
);
print "Copying files...\n";
[05/14] lucy-clownfish git commit: Move tests to separate directory
Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestString.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestString.c b/runtime/test/Clownfish/Test/TestString.c
new file mode 100644
index 0000000..d89b5fe
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestString.c
@@ -0,0 +1,848 @@
+/* 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 CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#include "Clownfish/Test/TestString.h"
+
+#include "Clownfish/String.h"
+#include "Clownfish/Boolean.h"
+#include "Clownfish/ByteBuf.h"
+#include "Clownfish/CharBuf.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Util/Memory.h"
+#include "Clownfish/Class.h"
+
+#define SMILEY "\xE2\x98\xBA"
+static char smiley[] = { (char)0xE2, (char)0x98, (char)0xBA, 0 };
+static uint32_t smiley_len = 3;
+static int32_t smiley_cp = 0x263A;
+
+TestString*
+TestStr_new() {
+ return (TestString*)Class_Make_Obj(TESTSTRING);
+}
+
+static String*
+S_get_str(const char *string) {
+ return Str_new_from_utf8(string, strlen(string));
+}
+
+// Surround a smiley with lots of whitespace.
+static String*
+S_smiley_with_whitespace(size_t *num_spaces_ptr) {
+ int32_t spaces[] = {
+ ' ', '\t', '\r', '\n', 0x000B, 0x000C, 0x000D, 0x0085,
+ 0x00A0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
+ 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029, 0x202F,
+ 0x205F, 0x3000
+ };
+ size_t num_spaces = sizeof(spaces) / sizeof(uint32_t);
+
+ CharBuf *buf = CB_new(0);
+ for (size_t i = 0; i < num_spaces; i++) { CB_Cat_Char(buf, spaces[i]); }
+ CB_Cat_Char(buf, smiley_cp);
+ for (size_t i = 0; i < num_spaces; i++) { CB_Cat_Char(buf, spaces[i]); }
+
+ String *retval = CB_To_String(buf);
+ if (num_spaces_ptr) { *num_spaces_ptr = num_spaces; }
+
+ DECREF(buf);
+ return retval;
+}
+
+static void
+test_new(TestBatchRunner *runner) {
+ static char chars[] = "A string " SMILEY " with a smile.";
+
+ {
+ char *buffer = (char*)MALLOCATE(sizeof(chars));
+ strcpy(buffer, chars);
+ String *thief = Str_new_steal_utf8(buffer, sizeof(chars) - 1);
+ TEST_TRUE(runner, Str_Equals_Utf8(thief, chars, sizeof(chars) - 1),
+ "Str_new_steal_utf8");
+ DECREF(thief);
+ }
+
+ {
+ char *buffer = (char*)MALLOCATE(sizeof(chars));
+ strcpy(buffer, chars);
+ String *thief
+ = Str_new_steal_trusted_utf8(buffer, sizeof(chars) - 1);
+ TEST_TRUE(runner, Str_Equals_Utf8(thief, chars, sizeof(chars) - 1),
+ "Str_new_steal_trusted_utf8");
+ DECREF(thief);
+ }
+
+ {
+ String *wrapper = Str_new_wrap_utf8(chars, sizeof(chars) - 1);
+ TEST_TRUE(runner, Str_Equals_Utf8(wrapper, chars, sizeof(chars) - 1),
+ "Str_new_wrap_utf8");
+ DECREF(wrapper);
+ }
+
+ {
+ String *wrapper = Str_new_wrap_trusted_utf8(chars, sizeof(chars) - 1);
+ TEST_TRUE(runner, Str_Equals_Utf8(wrapper, chars, sizeof(chars) - 1),
+ "Str_new_wrap_trusted_utf8");
+ DECREF(wrapper);
+ }
+
+ {
+ String *smiley_str = Str_new_from_char(smiley_cp);
+ TEST_TRUE(runner, Str_Equals_Utf8(smiley_str, smiley, smiley_len),
+ "Str_new_from_char");
+ DECREF(smiley_str);
+ }
+}
+
+static void
+test_Cat(TestBatchRunner *runner) {
+ String *wanted = Str_newf("a%s", smiley);
+ String *source;
+ String *got;
+
+ source = S_get_str("");
+ got = Str_Cat(source, wanted);
+ TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "Cat");
+ DECREF(got);
+ DECREF(source);
+
+ source = S_get_str("a");
+ got = Str_Cat_Utf8(source, smiley, smiley_len);
+ TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "Cat_Utf8");
+ DECREF(got);
+ DECREF(source);
+
+ source = S_get_str("a");
+ got = Str_Cat_Trusted_Utf8(source, smiley, smiley_len);
+ TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "Cat_Trusted_Utf8");
+ DECREF(got);
+ DECREF(source);
+
+ DECREF(wanted);
+}
+
+static void
+test_Clone(TestBatchRunner *runner) {
+ String *wanted = S_get_str("foo");
+ String *got = Str_Clone(wanted);
+ TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "Clone");
+ DECREF(got);
+ DECREF(wanted);
+}
+
+static int64_t
+S_find(String *string, String *substring) {
+ StringIterator *iter = Str_Find(string, substring);
+ if (iter == NULL) { return -1; }
+ size_t tick = StrIter_Recede(iter, SIZE_MAX);
+ DECREF(iter);
+ return (int64_t)tick;
+}
+
+static void
+test_Contains_and_Find(TestBatchRunner *runner) {
+ String *string;
+ String *substring = S_get_str("foo");
+ String *empty = S_get_str("");
+
+ TEST_FALSE(runner, Str_Contains(empty, substring),
+ "Not contained in empty string");
+ TEST_INT_EQ(runner, S_find(empty, substring), -1,
+ "Not found in empty string");
+
+ string = S_get_str("foo");
+ TEST_TRUE(runner, Str_Contains(string, substring),
+ "Contains complete string");
+ TEST_INT_EQ(runner, S_find(string, substring), 0, "Find complete string");
+ TEST_TRUE(runner, Str_Contains(string, empty),
+ "Contains empty string");
+ TEST_INT_EQ(runner, S_find(string, empty), 0, "Find empty string");
+ DECREF(string);
+
+ string = S_get_str("afoo");
+ TEST_TRUE(runner, Str_Contains(string, substring),
+ "Contained after first");
+ TEST_INT_EQ(runner, S_find(string, substring), 1, "Find after first");
+ String *prefix = Str_SubString(string, 0, 3);
+ TEST_FALSE(runner, Str_Contains(prefix, substring), "Don't overrun");
+ DECREF(prefix);
+ DECREF(string);
+
+ string = S_get_str("afood");
+ TEST_TRUE(runner, Str_Contains(string, substring), "Contained in middle");
+ TEST_INT_EQ(runner, S_find(string, substring), 1, "Find in middle");
+ DECREF(string);
+
+ DECREF(empty);
+ DECREF(substring);
+}
+
+static void
+test_Code_Point_At_and_From(TestBatchRunner *runner) {
+ int32_t code_points[] = {
+ 'a', smiley_cp, smiley_cp, 'b', smiley_cp, 'c'
+ };
+ uint32_t num_code_points = sizeof(code_points) / sizeof(int32_t);
+ String *string = Str_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;
+ TEST_INT_EQ(runner, Str_Code_Point_At(string, i), code_points[i],
+ "Code_Point_At %ld", (long)i);
+ TEST_INT_EQ(runner, Str_Code_Point_From(string, from),
+ code_points[i], "Code_Point_From %ld", (long)from);
+ }
+
+ TEST_INT_EQ(runner, Str_Code_Point_At(string, num_code_points), STR_OOB,
+ "Code_Point_At %ld", (long)num_code_points);
+ TEST_INT_EQ(runner, Str_Code_Point_From(string, 0), STR_OOB,
+ "Code_Point_From 0");
+ TEST_INT_EQ(runner, Str_Code_Point_From(string, num_code_points + 1),
+ STR_OOB, "Code_Point_From %ld", (long)(num_code_points + 1));
+
+ DECREF(string);
+}
+
+static void
+test_SubString(TestBatchRunner *runner) {
+ {
+ String *string = Str_newf("a%s%sb%sc", smiley, smiley, smiley);
+ String *wanted = Str_newf("%sb%s", smiley, smiley);
+ String *got = Str_SubString(string, 2, 3);
+ TEST_TRUE(runner, Str_Equals(wanted, (Obj*)got), "SubString");
+ DECREF(string);
+ DECREF(wanted);
+ DECREF(got);
+ }
+
+ {
+ static const char chars[] = "A string.";
+ String *wrapper = Str_new_wrap_utf8(chars, sizeof(chars) - 1);
+ String *wanted = Str_newf("string");
+ String *got = Str_SubString(wrapper, 2, 6);
+ TEST_TRUE(runner, Str_Equals(got, (Obj*)wanted),
+ "SubString with wrapped buffer");
+ DECREF(wrapper);
+ DECREF(wanted);
+ DECREF(got);
+ }
+}
+
+static void
+test_Trim(TestBatchRunner *runner) {
+ String *ws_smiley = S_smiley_with_whitespace(NULL);
+ String *ws_foo = S_get_str(" foo ");
+ String *ws_only = S_get_str(" \t \r\n");
+ String *trimmed = S_get_str("a b");
+ String *got;
+
+ got = Str_Trim(ws_smiley);
+ TEST_TRUE(runner, Str_Equals_Utf8(got, smiley, smiley_len), "Trim");
+ DECREF(got);
+
+ got = Str_Trim_Top(ws_foo);
+ TEST_TRUE(runner, Str_Equals_Utf8(got, "foo ", 5), "Trim_Top");
+ DECREF(got);
+
+ got = Str_Trim_Tail(ws_foo);
+ TEST_TRUE(runner, Str_Equals_Utf8(got, " foo", 5), "Trim_Tail");
+ DECREF(got);
+
+ got = Str_Trim(ws_only);
+ TEST_TRUE(runner, Str_Equals_Utf8(got, "", 0), "Trim with only whitespace");
+ DECREF(got);
+
+ got = Str_Trim_Top(ws_only);
+ TEST_TRUE(runner, Str_Equals_Utf8(got, "", 0),
+ "Trim_Top with only whitespace");
+ DECREF(got);
+
+ got = Str_Trim_Tail(ws_only);
+ TEST_TRUE(runner, Str_Equals_Utf8(got, "", 0),
+ "Trim_Tail with only whitespace");
+ DECREF(got);
+
+ got = Str_Trim(trimmed);
+ TEST_TRUE(runner, Str_Equals(got, (Obj*)trimmed),
+ "Trim doesn't change trimmed string");
+ DECREF(got);
+
+ got = Str_Trim_Top(trimmed);
+ TEST_TRUE(runner, Str_Equals(got, (Obj*)trimmed),
+ "Trim_Top doesn't change trimmed string");
+ DECREF(got);
+
+ got = Str_Trim_Tail(trimmed);
+ TEST_TRUE(runner, Str_Equals(got, (Obj*)trimmed),
+ "Trim_Tail doesn't change trimmed string");
+ DECREF(got);
+
+ DECREF(trimmed);
+ DECREF(ws_only);
+ DECREF(ws_foo);
+ DECREF(ws_smiley);
+}
+
+static void
+test_To_F64(TestBatchRunner *runner) {
+ String *string;
+
+ string = S_get_str("1.5");
+ double difference = 1.5 - Str_To_F64(string);
+ if (difference < 0) { difference = 0 - difference; }
+ TEST_TRUE(runner, difference < 0.001, "To_F64");
+ DECREF(string);
+
+ string = S_get_str("-1.5");
+ difference = 1.5 + Str_To_F64(string);
+ if (difference < 0) { difference = 0 - difference; }
+ TEST_TRUE(runner, difference < 0.001, "To_F64 negative");
+ DECREF(string);
+
+ // TODO: Enable this test when we have real substrings.
+ /*string = S_get_str("1.59");
+ double value_full = Str_To_F64(string);
+ Str_Set_Size(string, 3);
+ double value_short = Str_To_F64(string);
+ TEST_TRUE(runner, value_short < value_full,
+ "TO_F64 doesn't run past end of string");
+ DECREF(string);*/
+}
+
+static void
+test_To_I64(TestBatchRunner *runner) {
+ String *string;
+
+ string = S_get_str("10");
+ TEST_INT_EQ(runner, Str_To_I64(string), 10, "To_I64");
+ DECREF(string);
+
+ string = S_get_str("-10");
+ TEST_INT_EQ(runner, Str_To_I64(string), -10, "To_I64 negative");
+ DECREF(string);
+
+ string = S_get_str("10.");
+ TEST_INT_EQ(runner, Str_To_I64(string), 10, "To_I64 stops at non-digits");
+ DECREF(string);
+
+ string = S_get_str("10" SMILEY);
+ TEST_INT_EQ(runner, Str_To_I64(string), 10, "To_I64 stops at non-ASCII");
+ DECREF(string);
+
+ string = S_get_str("10A");
+ TEST_INT_EQ(runner, Str_To_I64(string), 10,
+ "To_I64 stops at out-of-range digits");
+ DECREF(string);
+}
+
+static void
+test_BaseX_To_I64(TestBatchRunner *runner) {
+ String *string;
+
+ string = S_get_str("-JJ");
+ TEST_INT_EQ(runner, Str_BaseX_To_I64(string, 20), -399,
+ "BaseX_To_I64 base 20");
+ DECREF(string);
+}
+
+static void
+test_To_String(TestBatchRunner *runner) {
+ String *string = Str_newf("Test");
+ String *copy = Str_To_String(string);
+ TEST_TRUE(runner, Str_Equals(copy, (Obj*)string), "To_String");
+ DECREF(string);
+ DECREF(copy);
+}
+
+static void
+test_To_Utf8(TestBatchRunner *runner) {
+ String *string = Str_newf("a%s%sb%sc", smiley, smiley, smiley);
+ char *buf = Str_To_Utf8(string);
+ TEST_TRUE(runner, strcmp(buf, "a" SMILEY SMILEY "b" SMILEY "c") == 0,
+ "To_Utf8");
+ FREEMEM(buf);
+ DECREF(string);
+}
+
+static void
+test_To_ByteBuf(TestBatchRunner *runner) {
+ String *string = Str_newf("foo");
+ ByteBuf *bb = Str_To_ByteBuf(string);
+ TEST_TRUE(runner, BB_Equals_Bytes(bb, "foo", 3), "To_ByteBuf");
+ DECREF(bb);
+ DECREF(string);
+}
+
+static void
+test_Length(TestBatchRunner *runner) {
+ String *string = Str_newf("a%s%sb%sc", smiley, smiley, smiley);
+ TEST_UINT_EQ(runner, Str_Length(string), 6, "Length");
+ DECREF(string);
+}
+
+static void
+test_Compare_To(TestBatchRunner *runner) {
+ String *abc = Str_newf("a%s%sb%sc", smiley, smiley, smiley);
+ String *ab = Str_newf("a%s%sb", smiley, smiley);
+ String *ac = Str_newf("a%s%sc", smiley, smiley);
+
+ TEST_TRUE(runner, Str_Compare_To(abc, (Obj*)abc) == 0,
+ "Compare_To abc abc");
+ TEST_TRUE(runner, Str_Compare_To(ab, (Obj*)abc) < 0,
+ "Compare_To ab abc");
+ TEST_TRUE(runner, Str_Compare_To(abc, (Obj*)ab) > 0,
+ "Compare_To abc ab");
+ TEST_TRUE(runner, Str_Compare_To(ab, (Obj*)ac) < 0,
+ "Compare_To ab ac");
+ TEST_TRUE(runner, Str_Compare_To(ac, (Obj*)ab) > 0,
+ "Compare_To ac ab");
+
+ DECREF(ac);
+ DECREF(ab);
+ DECREF(abc);
+}
+
+static void
+test_Starts_Ends_With(TestBatchRunner *runner) {
+ String *prefix = S_get_str("pre" SMILEY "fix_");
+ String *suffix = S_get_str("_post" SMILEY "fix");
+ String *empty = S_get_str("");
+
+ TEST_TRUE(runner, Str_Starts_With(suffix, suffix),
+ "Starts_With self returns true");
+ TEST_TRUE(runner, Str_Ends_With(prefix, prefix),
+ "Ends_With self returns true");
+
+ TEST_TRUE(runner, Str_Starts_With(suffix, empty),
+ "Starts_With empty string returns true");
+ TEST_TRUE(runner, Str_Ends_With(prefix, empty),
+ "Ends_With empty string returns true");
+ TEST_FALSE(runner, Str_Starts_With(empty, suffix),
+ "Empty string Starts_With returns false");
+ TEST_FALSE(runner, Str_Ends_With(empty, prefix),
+ "Empty string Ends_With returns false");
+
+ {
+ String *string
+ = S_get_str("pre" SMILEY "fix_string_post" SMILEY "fix");
+ TEST_TRUE(runner, Str_Starts_With(string, prefix),
+ "Starts_With returns true");
+ TEST_TRUE(runner, Str_Ends_With(string, suffix),
+ "Ends_With returns true");
+ DECREF(string);
+ }
+
+ {
+ String *string
+ = S_get_str("pre" SMILEY "fix:string:post" SMILEY "fix");
+ TEST_FALSE(runner, Str_Starts_With(string, prefix),
+ "Starts_With returns false");
+ TEST_FALSE(runner, Str_Ends_With(string, suffix),
+ "Ends_With returns false");
+ DECREF(string);
+ }
+
+ DECREF(prefix);
+ DECREF(suffix);
+ DECREF(empty);
+}
+
+static void
+test_Starts_Ends_With_Utf8(TestBatchRunner *runner) {
+ String *str = S_get_str("pre" SMILEY "post");
+
+ static const char prefix[] = "pre" SMILEY;
+ static const char postfix[] = SMILEY "post";
+ static const size_t prefix_size = sizeof(prefix) - 1;
+ static const size_t postfix_size = sizeof(postfix) - 1;
+ TEST_TRUE(runner, Str_Starts_With_Utf8(str, prefix, prefix_size),
+ "Starts_With_Utf8 returns true");
+ TEST_TRUE(runner, Str_Ends_With_Utf8(str, postfix, postfix_size),
+ "Ends_With_Utf8 returns true");
+ TEST_FALSE(runner, Str_Starts_With_Utf8(str, postfix, postfix_size),
+ "Starts_With_Utf8 returns false");
+ TEST_FALSE(runner, Str_Ends_With_Utf8(str, prefix, prefix_size),
+ "Ends_With_Utf8 returns false");
+
+ static const char longer[] = "12345678901234567890";
+ static const size_t longer_size = sizeof(longer) - 1;
+ TEST_FALSE(runner, Str_Starts_With_Utf8(str, longer, longer_size),
+ "Starts_With_Utf8 longer str returns false");
+ TEST_FALSE(runner, Str_Ends_With_Utf8(str, longer, longer_size),
+ "Ends_With_Utf8 longer str returns false");
+
+ DECREF(str);
+}
+
+static void
+test_Get_Ptr8(TestBatchRunner *runner) {
+ String *string = S_get_str("Banana");
+
+ const char *ptr8 = Str_Get_Ptr8(string);
+ TEST_TRUE(runner, strcmp(ptr8, "Banana") == 0, "Get_Ptr8");
+
+ size_t size = Str_Get_Size(string);
+ TEST_UINT_EQ(runner, size, 6, "Get_Size");
+
+ DECREF(string);
+}
+
+static void
+test_iterator(TestBatchRunner *runner) {
+ static const int32_t code_points[] = {
+ 0x41,
+ 0x7F,
+ 0x80,
+ 0x7FF,
+ 0x800,
+ 0xFFFF,
+ 0x10000,
+ 0x10FFFF
+ };
+ static size_t num_code_points
+ = sizeof(code_points) / sizeof(code_points[0]);
+
+ CharBuf *buf = CB_new(0);
+ for (size_t i = 0; i < num_code_points; ++i) {
+ CB_Cat_Char(buf, code_points[i]);
+ }
+ String *string = CB_To_String(buf);
+
+ {
+ StringIterator *iter = Str_Top(string);
+
+ TEST_TRUE(runner, StrIter_Equals(iter, (Obj*)iter),
+ "StringIterator equal to self");
+ TEST_FALSE(runner, StrIter_Equals(iter, (Obj*)CFISH_TRUE),
+ "StringIterator not equal non-iterators");
+
+ DECREF(iter);
+ }
+
+ {
+ StringIterator *top = Str_Top(string);
+ StringIterator *tail = Str_Tail(string);
+
+ TEST_FALSE(runner, StrIter_Equals(top, (Obj*)tail),
+ "StrIter_Equals returns false");
+
+ TEST_INT_EQ(runner, StrIter_Compare_To(top, (Obj*)tail), -1,
+ "Compare_To top < tail");
+ TEST_INT_EQ(runner, StrIter_Compare_To(tail, (Obj*)top), 1,
+ "Compare_To tail > top");
+ TEST_INT_EQ(runner, StrIter_Compare_To(top, (Obj*)top), 0,
+ "Compare_To top == top");
+
+ StringIterator *clone = StrIter_Clone(top);
+ TEST_TRUE(runner, StrIter_Equals(clone, (Obj*)top), "Clone");
+
+ StrIter_Assign(clone, tail);
+ TEST_TRUE(runner, StrIter_Equals(clone, (Obj*)tail), "Assign");
+
+ String *other = Str_newf("Other string");
+ StringIterator *other_iter = Str_Top(other);
+ TEST_FALSE(runner, StrIter_Equals(other_iter, (Obj*)tail),
+ "Equals returns false for different strings");
+ StrIter_Assign(clone, other_iter);
+ TEST_TRUE(runner, StrIter_Equals(clone, (Obj*)other_iter),
+ "Assign iterator with different string");
+
+ DECREF(other);
+ DECREF(other_iter);
+ DECREF(clone);
+ DECREF(top);
+ DECREF(tail);
+ }
+
+ {
+ StringIterator *iter = Str_Top(string);
+
+ for (size_t i = 0; i < num_code_points; ++i) {
+ TEST_TRUE(runner, StrIter_Has_Next(iter), "Has_Next %d", i);
+ int32_t code_point = StrIter_Next(iter);
+ TEST_INT_EQ(runner, code_point, code_points[i], "Next %d", i);
+ }
+
+ TEST_TRUE(runner, !StrIter_Has_Next(iter),
+ "Has_Next at end of string");
+ TEST_INT_EQ(runner, StrIter_Next(iter), STR_OOB,
+ "Next at end of string");
+
+ StringIterator *tail = Str_Tail(string);
+ TEST_TRUE(runner, StrIter_Equals(iter, (Obj*)tail), "Equals tail");
+
+ DECREF(tail);
+ DECREF(iter);
+ }
+
+ {
+ StringIterator *iter = Str_Tail(string);
+
+ for (size_t i = num_code_points; i--;) {
+ TEST_TRUE(runner, StrIter_Has_Prev(iter), "Has_Prev %d", i);
+ int32_t code_point = StrIter_Prev(iter);
+ TEST_INT_EQ(runner, code_point, code_points[i], "Prev %d", i);
+ }
+
+ TEST_TRUE(runner, !StrIter_Has_Prev(iter),
+ "Has_Prev at end of string");
+ TEST_INT_EQ(runner, StrIter_Prev(iter), STR_OOB,
+ "Prev at start of string");
+
+ StringIterator *top = Str_Top(string);
+ TEST_TRUE(runner, StrIter_Equals(iter, (Obj*)top), "Equals top");
+
+ DECREF(top);
+ DECREF(iter);
+ }
+
+ {
+ StringIterator *iter = Str_Top(string);
+
+ StrIter_Next(iter);
+ TEST_UINT_EQ(runner, StrIter_Advance(iter, 2), 2,
+ "Advance returns number of code points");
+ TEST_INT_EQ(runner, StrIter_Next(iter), code_points[3],
+ "Advance works");
+ TEST_UINT_EQ(runner,
+ StrIter_Advance(iter, 1000000), num_code_points - 4,
+ "Advance past end of string");
+
+ StrIter_Prev(iter);
+ TEST_UINT_EQ(runner, StrIter_Recede(iter, 2), 2,
+ "Recede returns number of code points");
+ TEST_INT_EQ(runner, StrIter_Prev(iter), code_points[num_code_points-4],
+ "Recede works");
+ TEST_UINT_EQ(runner, StrIter_Recede(iter, 1000000), num_code_points - 4,
+ "Recede past start of string");
+
+ DECREF(iter);
+ }
+
+ DECREF(string);
+ DECREF(buf);
+}
+
+static void
+test_iterator_whitespace(TestBatchRunner *runner) {
+ size_t num_spaces;
+ String *ws_smiley = S_smiley_with_whitespace(&num_spaces);
+
+ {
+ StringIterator *iter = Str_Top(ws_smiley);
+ TEST_UINT_EQ(runner, StrIter_Skip_Whitespace(iter), num_spaces,
+ "Skip_Whitespace");
+ TEST_UINT_EQ(runner, StrIter_Skip_Whitespace(iter), 0,
+ "Skip_Whitespace without whitespace");
+ DECREF(iter);
+ }
+
+ {
+ StringIterator *iter = Str_Tail(ws_smiley);
+ TEST_UINT_EQ(runner, StrIter_Skip_Whitespace_Back(iter), num_spaces,
+ "Skip_Whitespace_Back");
+ TEST_UINT_EQ(runner, StrIter_Skip_Whitespace_Back(iter), 0,
+ "Skip_Whitespace_Back without whitespace");
+ DECREF(iter);
+ }
+
+ DECREF(ws_smiley);
+}
+
+typedef struct {
+ StringIterator *top;
+ StringIterator *tail;
+} StrIterCropContext;
+
+static void
+S_striter_crop(void *vcontext) {
+ StrIterCropContext *context = (StrIterCropContext*)vcontext;
+ StrIter_crop(context->top, context->tail);
+}
+
+static void
+test_iterator_substring(TestBatchRunner *runner) {
+ String *string = Str_newf("a%sb%sc%sd", smiley, smiley, smiley);
+
+ StringIterator *start = Str_Top(string);
+ StringIterator *end = Str_Tail(string);
+
+ {
+ String *substring = StrIter_crop(start, end);
+ TEST_TRUE(runner, Str_Equals(substring, (Obj*)string),
+ "StrIter_crop whole string");
+ DECREF(substring);
+ }
+
+ StrIter_Advance(start, 2);
+ StrIter_Recede(end, 2);
+
+ {
+ String *substring = StrIter_crop(start, end);
+ static const char wanted_buf[] = "b" SMILEY "c";
+ static const size_t wanted_size = sizeof(wanted_buf) - 1;
+ String *wanted = Str_new_from_utf8(wanted_buf, wanted_size);
+ TEST_TRUE(runner, Str_Equals(substring, (Obj*)wanted),
+ "StrIter_crop");
+
+ TEST_TRUE(runner, StrIter_Starts_With(start, wanted),
+ "Starts_With returns true");
+ TEST_TRUE(runner, StrIter_Ends_With(end, wanted),
+ "Ends_With returns true");
+ TEST_TRUE(runner,
+ StrIter_Starts_With_Utf8(start, wanted_buf, wanted_size),
+ "Starts_With_Utf8 returns true");
+ TEST_TRUE(runner,
+ StrIter_Ends_With_Utf8(end, wanted_buf, wanted_size),
+ "Ends_With_Utf8 returns true");
+
+ DECREF(wanted);
+ DECREF(substring);
+ }
+
+ {
+ static const char short_buf[] = "b" SMILEY "x";
+ static const size_t short_size = sizeof(short_buf) - 1;
+ String *short_str = Str_new_from_utf8(short_buf, short_size);
+ TEST_FALSE(runner, StrIter_Starts_With(start, short_str),
+ "Starts_With returns false");
+ TEST_FALSE(runner, StrIter_Ends_With(start, short_str),
+ "Ends_With returns false");
+ TEST_FALSE(runner,
+ StrIter_Starts_With_Utf8(start, short_buf, short_size),
+ "Starts_With_Utf8 returns false");
+ TEST_FALSE(runner,
+ StrIter_Ends_With_Utf8(start, short_buf, short_size),
+ "Ends_With_Utf8 returns false");
+
+ static const char long_buf[] = "b" SMILEY "xxxxxxxxxxxx" SMILEY "c";
+ static const size_t long_size = sizeof(long_buf) - 1;
+ String *long_str = Str_new_from_utf8(long_buf, long_size);
+ TEST_FALSE(runner, StrIter_Starts_With(start, long_str),
+ "Starts_With long string returns false");
+ TEST_FALSE(runner, StrIter_Ends_With(end, long_str),
+ "Ends_With long string returns false");
+ TEST_FALSE(runner,
+ StrIter_Starts_With_Utf8(start, long_buf, long_size),
+ "Starts_With_Utf8 long string returns false");
+ TEST_FALSE(runner,
+ StrIter_Ends_With_Utf8(end, long_buf, long_size),
+ "Ends_With_Utf8 long string returns false");
+
+ DECREF(short_str);
+ DECREF(long_str);
+ }
+
+ {
+ String *substring = StrIter_crop(end, NULL);
+ String *wanted = Str_newf("%sd", smiley);
+ TEST_TRUE(runner, Str_Equals(substring, (Obj*)wanted),
+ "StrIter_crop with NULL tail");
+ DECREF(wanted);
+ DECREF(substring);
+ }
+
+ {
+ String *substring = StrIter_crop(NULL, start);
+ String *wanted = Str_newf("a%s", smiley);
+ TEST_TRUE(runner, Str_Equals(substring, (Obj*)wanted),
+ "StrIter_crop with NULL top");
+ DECREF(wanted);
+ DECREF(substring);
+ }
+
+ {
+ StrIterCropContext context;
+ context.top = NULL;
+ context.tail = NULL;
+ Err *error = Err_trap(S_striter_crop, &context);
+ TEST_TRUE(runner, error != NULL,
+ "StrIter_crop throws if top and tail are NULL");
+ DECREF(error);
+ }
+
+ {
+ String *other = SSTR_WRAP_C("other");
+ StrIterCropContext context;
+ context.top = start;
+ context.tail = Str_Tail(other);
+ Err *error = Err_trap(S_striter_crop, &context);
+ TEST_TRUE(runner, error != NULL,
+ "StrIter_crop throws if string don't match");
+ DECREF(error);
+ DECREF(context.tail);
+ }
+
+ {
+ StrIterCropContext context;
+ context.top = end;
+ context.tail = start;
+ Err *error = Err_trap(S_striter_crop, &context);
+ TEST_TRUE(runner, error != NULL,
+ "StrIter_crop throws if top is behind tail");
+ DECREF(error);
+ }
+
+ DECREF(start);
+ DECREF(end);
+ DECREF(string);
+}
+
+void
+TestStr_Run_IMP(TestString *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 158);
+ test_new(runner);
+ test_Cat(runner);
+ test_Clone(runner);
+ test_Code_Point_At_and_From(runner);
+ test_Contains_and_Find(runner);
+ test_SubString(runner);
+ test_Trim(runner);
+ test_To_F64(runner);
+ test_To_I64(runner);
+ test_BaseX_To_I64(runner);
+ test_To_String(runner);
+ test_To_Utf8(runner);
+ test_To_ByteBuf(runner);
+ test_Length(runner);
+ test_Compare_To(runner);
+ test_Starts_Ends_With(runner);
+ test_Starts_Ends_With_Utf8(runner);
+ test_Get_Ptr8(runner);
+ test_iterator(runner);
+ test_iterator_whitespace(runner);
+ test_iterator_substring(runner);
+}
+
+/*************************** StringCallbackTest ***************************/
+
+bool
+StrCbTest_Unchanged_By_Callback_IMP(StringCallbackTest *self, String *str) {
+ String *before = Str_Clone(str);
+ StrCbTest_Callback(self);
+ return Str_Equals(str, (Obj*)before);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestString.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestString.cfh b/runtime/test/Clownfish/Test/TestString.cfh
new file mode 100644
index 0000000..88e43c9
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestString.cfh
@@ -0,0 +1,36 @@
+/* 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::TestString nickname TestStr
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestString*
+ new();
+
+ void
+ Run(TestString *self, TestBatchRunner *runner);
+}
+
+abstract class Clownfish::Test::StringCallbackTest nickname StrCbTest {
+ bool
+ Unchanged_By_Callback(StringCallbackTest *self, String *str);
+
+ abstract void
+ Callback(StringCallbackTest *self);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestVector.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestVector.c b/runtime/test/Clownfish/Test/TestVector.c
new file mode 100644
index 0000000..17a7f98
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestVector.c
@@ -0,0 +1,572 @@
+/* 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 <stdlib.h>
+
+#define C_CFISH_VECTOR
+#define CFISH_USE_SHORT_NAMES
+#define TESTCFISH_USE_SHORT_NAMES
+
+#define MAX_VECTOR_SIZE (SIZE_MAX / sizeof(Obj*))
+
+#include "Clownfish/Test/TestVector.h"
+
+#include "Clownfish/String.h"
+#include "Clownfish/Boolean.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Num.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Vector.h"
+#include "Clownfish/Class.h"
+
+TestVector*
+TestVector_new() {
+ return (TestVector*)Class_Make_Obj(TESTVECTOR);
+}
+
+// Return an array of size 10 with 30 garbage pointers behind.
+static Vector*
+S_array_with_garbage() {
+ Vector *array = Vec_new(100);
+
+ for (int i = 0; i < 40; i++) {
+ Vec_Push(array, (Obj*)CFISH_TRUE);
+ }
+
+ // Remove elements using different methods.
+ Vec_Excise(array, 10, 10);
+ for (int i = 0; i < 10; i++) { Vec_Pop(array); }
+ Vec_Resize(array, 10);
+
+ return array;
+}
+
+static void
+test_Equals(TestBatchRunner *runner) {
+ Vector *array = Vec_new(0);
+ Vector *other = Vec_new(0);
+ String *stuff = SSTR_WRAP_C("stuff");
+
+ TEST_TRUE(runner, Vec_Equals(array, (Obj*)array),
+ "Array equal to self");
+
+ TEST_FALSE(runner, Vec_Equals(array, (Obj*)CFISH_TRUE),
+ "Array not equal to non-array");
+
+ TEST_TRUE(runner, Vec_Equals(array, (Obj*)other),
+ "Empty arrays are equal");
+
+ Vec_Push(array, (Obj*)CFISH_TRUE);
+ TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
+ "Add one elem and Equals returns false");
+
+ Vec_Push(other, (Obj*)CFISH_TRUE);
+ TEST_TRUE(runner, Vec_Equals(array, (Obj*)other),
+ "Add a matching elem and Equals returns true");
+
+ Vec_Store(array, 2, (Obj*)CFISH_TRUE);
+ TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
+ "Add elem after a NULL and Equals returns false");
+
+ Vec_Store(other, 2, (Obj*)CFISH_TRUE);
+ TEST_TRUE(runner, Vec_Equals(array, (Obj*)other),
+ "Empty elems don't spoil Equals");
+
+ Vec_Store(other, 2, INCREF(stuff));
+ TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
+ "Non-matching value spoils Equals");
+
+ Vec_Store(other, 2, NULL);
+ TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
+ "NULL value spoils Equals");
+ TEST_FALSE(runner, Vec_Equals(other, (Obj*)array),
+ "NULL value spoils Equals (reversed)");
+
+ Vec_Excise(array, 1, 2); // removes empty elems
+ DECREF(Vec_Delete(other, 1)); // leaves NULL in place of deleted elem
+ DECREF(Vec_Delete(other, 2));
+ TEST_FALSE(runner, Vec_Equals(array, (Obj*)other),
+ "Empty trailing elements spoil Equals");
+
+ DECREF(array);
+ DECREF(other);
+}
+
+static void
+test_Store_Fetch(TestBatchRunner *runner) {
+ Vector *array = Vec_new(0);
+ String *elem;
+
+ TEST_TRUE(runner, Vec_Fetch(array, 2) == NULL, "Fetch beyond end");
+
+ Vec_Store(array, 2, (Obj*)Str_newf("foo"));
+ elem = (String*)CERTIFY(Vec_Fetch(array, 2), STRING);
+ TEST_UINT_EQ(runner, 3, Vec_Get_Size(array), "Store updates size");
+ TEST_TRUE(runner, Str_Equals_Utf8(elem, "foo", 3), "Store");
+
+ elem = (String*)INCREF(elem);
+ TEST_INT_EQ(runner, 2, CFISH_REFCOUNT_NN(elem),
+ "start with refcount of 2");
+ Vec_Store(array, 2, (Obj*)Str_newf("bar"));
+ TEST_INT_EQ(runner, 1, CFISH_REFCOUNT_NN(elem),
+ "Displacing elem via Store updates refcount");
+ DECREF(elem);
+ elem = (String*)CERTIFY(Vec_Fetch(array, 2), STRING);
+ TEST_TRUE(runner, Str_Equals_Utf8(elem, "bar", 3), "Store displacement");
+
+ DECREF(array);
+
+ array = S_array_with_garbage();
+ Vec_Store(array, 40, (Obj*)CFISH_TRUE);
+ bool all_null = true;
+ for (size_t i = 10; i < 40; i++) {
+ if (Vec_Fetch(array, i) != NULL) { all_null = false; }
+ }
+ TEST_TRUE(runner, all_null, "Out-of-bounds Store clears excised elements");
+ DECREF(array);
+}
+
+static void
+test_Push_Pop_Insert(TestBatchRunner *runner) {
+ Vector *array = Vec_new(0);
+ String *elem;
+
+ TEST_UINT_EQ(runner, Vec_Get_Size(array), 0, "size starts at 0");
+ TEST_TRUE(runner, Vec_Pop(array) == NULL,
+ "Pop from empty array returns NULL");
+
+ Vec_Push(array, (Obj*)Str_newf("a"));
+ Vec_Push(array, (Obj*)Str_newf("b"));
+ Vec_Push(array, (Obj*)Str_newf("c"));
+
+ TEST_UINT_EQ(runner, Vec_Get_Size(array), 3, "size after Push");
+ TEST_TRUE(runner, NULL != CERTIFY(Vec_Fetch(array, 2), STRING), "Push");
+
+ elem = (String*)CERTIFY(Vec_Pop(array), STRING);
+ TEST_TRUE(runner, Str_Equals_Utf8(elem, "c", 1), "Pop");
+ TEST_UINT_EQ(runner, Vec_Get_Size(array), 2, "size after Pop");
+ DECREF(elem);
+
+ Vec_Insert(array, 0, (Obj*)Str_newf("foo"));
+ elem = (String*)CERTIFY(Vec_Fetch(array, 0), STRING);
+ TEST_TRUE(runner, Str_Equals_Utf8(elem, "foo", 3), "Insert");
+ TEST_UINT_EQ(runner, Vec_Get_Size(array), 3, "size after Insert");
+
+ for (int i = 0; i < 256; ++i) {
+ Vec_Push(array, (Obj*)Str_newf("flotsam"));
+ }
+ for (size_t i = 0; i < 512; ++i) {
+ Vec_Insert(array, i, (Obj*)Str_newf("jetsam"));
+ }
+ TEST_UINT_EQ(runner, Vec_Get_Size(array), 3 + 256 + 512,
+ "size after exercising Push and Insert");
+
+ DECREF(array);
+}
+
+static void
+test_Insert_All(TestBatchRunner *runner) {
+ int64_t i;
+
+ {
+ Vector *dst = Vec_new(20);
+ Vector *src = Vec_new(10);
+ Vector *wanted = Vec_new(30);
+
+ for (i = 0; i < 10; i++) { Vec_Push(dst, (Obj*)Int_new(i)); }
+ for (i = 0; i < 10; i++) { Vec_Push(dst, (Obj*)Int_new(i + 20)); }
+ for (i = 0; i < 10; i++) { Vec_Push(src, (Obj*)Int_new(i + 10)); }
+ for (i = 0; i < 30; i++) { Vec_Push(wanted, (Obj*)Int_new(i)); }
+
+ Vec_Insert_All(dst, 10, src);
+ TEST_TRUE(runner, Vec_Equals(dst, (Obj*)wanted), "Insert_All between");
+
+ DECREF(wanted);
+ DECREF(src);
+ DECREF(dst);
+ }
+
+ {
+ Vector *dst = Vec_new(10);
+ Vector *src = Vec_new(10);
+ Vector *wanted = Vec_new(30);
+
+ for (i = 0; i < 10; i++) { Vec_Push(dst, (Obj*)Int_new(i)); }
+ for (i = 0; i < 10; i++) { Vec_Push(src, (Obj*)Int_new(i + 20)); }
+ for (i = 0; i < 10; i++) { Vec_Push(wanted, (Obj*)Int_new(i)); }
+ for (i = 0; i < 10; i++) {
+ Vec_Store(wanted, (size_t)i + 20, (Obj*)Int_new(i + 20));
+ }
+
+ Vec_Insert_All(dst, 20, src);
+ TEST_TRUE(runner, Vec_Equals(dst, (Obj*)wanted), "Insert_All after");
+
+ DECREF(wanted);
+ DECREF(src);
+ DECREF(dst);
+ }
+}
+
+static void
+test_Delete(TestBatchRunner *runner) {
+ Vector *wanted = Vec_new(5);
+ Vector *got = Vec_new(5);
+ uint32_t i;
+
+ for (i = 0; i < 5; i++) { Vec_Push(got, (Obj*)Str_newf("%u32", i)); }
+ Vec_Store(wanted, 0, (Obj*)Str_newf("0", i));
+ Vec_Store(wanted, 1, (Obj*)Str_newf("1", i));
+ Vec_Store(wanted, 4, (Obj*)Str_newf("4", i));
+ DECREF(Vec_Delete(got, 2));
+ DECREF(Vec_Delete(got, 3));
+ TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got), "Delete");
+
+ TEST_TRUE(runner, Vec_Delete(got, 25000) == NULL,
+ "Delete beyond array size returns NULL");
+
+ DECREF(wanted);
+ DECREF(got);
+}
+
+static void
+test_Resize(TestBatchRunner *runner) {
+ Vector *array = Vec_new(3);
+ uint32_t i;
+
+ for (i = 0; i < 2; i++) { Vec_Push(array, (Obj*)Str_newf("%u32", i)); }
+ TEST_UINT_EQ(runner, Vec_Get_Capacity(array), 3, "Start with capacity 3");
+
+ Vec_Resize(array, 4);
+ TEST_UINT_EQ(runner, Vec_Get_Size(array), 4, "Resize up");
+ TEST_UINT_EQ(runner, Vec_Get_Capacity(array), 4,
+ "Resize changes capacity");
+
+ Vec_Resize(array, 2);
+ TEST_UINT_EQ(runner, Vec_Get_Size(array), 2, "Resize down");
+ TEST_TRUE(runner, Vec_Fetch(array, 2) == NULL, "Resize down zaps elem");
+
+ Vec_Resize(array, 2);
+ TEST_UINT_EQ(runner, Vec_Get_Size(array), 2, "Resize to same size");
+
+ DECREF(array);
+
+ array = S_array_with_garbage();
+ Vec_Resize(array, 40);
+ bool all_null = true;
+ for (size_t i = 10; i < 40; i++) {
+ if (Vec_Fetch(array, i) != NULL) { all_null = false; }
+ }
+ TEST_TRUE(runner, all_null, "Resize clears excised elements");
+ DECREF(array);
+}
+
+static void
+test_Excise(TestBatchRunner *runner) {
+ Vector *wanted = Vec_new(5);
+ Vector *got = Vec_new(5);
+
+ for (uint32_t i = 0; i < 5; i++) {
+ Vec_Push(wanted, (Obj*)Str_newf("%u32", i));
+ Vec_Push(got, (Obj*)Str_newf("%u32", i));
+ }
+
+ Vec_Excise(got, 7, 1);
+ TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
+ "Excise outside of range is no-op");
+
+ Vec_Excise(got, 2, 2);
+ DECREF(Vec_Delete(wanted, 2));
+ DECREF(Vec_Delete(wanted, 3));
+ Vec_Store(wanted, 2, Vec_Delete(wanted, 4));
+ Vec_Resize(wanted, 3);
+ TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
+ "Excise multiple elems");
+
+ Vec_Excise(got, 2, 2);
+ Vec_Resize(wanted, 2);
+ TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
+ "Splicing too many elems truncates");
+
+ Vec_Excise(got, 0, 1);
+ Vec_Store(wanted, 0, Vec_Delete(wanted, 1));
+ Vec_Resize(wanted, 1);
+ TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
+ "Excise first elem");
+
+ DECREF(got);
+ DECREF(wanted);
+}
+
+static void
+test_Push_All(TestBatchRunner *runner) {
+ Vector *wanted = Vec_new(0);
+ Vector *got = Vec_new(0);
+ Vector *scratch = Vec_new(0);
+ Vector *empty = Vec_new(0);
+ uint32_t i;
+
+ for (i = 0; i < 40; i++) { Vec_Push(wanted, (Obj*)Str_newf("%u32", i)); }
+ Vec_Push(wanted, NULL);
+ for (i = 0; i < 20; i++) { Vec_Push(got, (Obj*)Str_newf("%u32", i)); }
+ for (i = 20; i < 40; i++) { Vec_Push(scratch, (Obj*)Str_newf("%u32", i)); }
+ Vec_Push(scratch, NULL);
+
+ Vec_Push_All(got, scratch);
+ TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got), "Push_All");
+
+ Vec_Push_All(got, empty);
+ TEST_TRUE(runner, Vec_Equals(wanted, (Obj*)got),
+ "Push_All with empty array");
+
+ DECREF(wanted);
+ DECREF(got);
+ DECREF(scratch);
+ DECREF(empty);
+}
+
+static void
+test_Slice(TestBatchRunner *runner) {
+ Vector *array = Vec_new(0);
+ for (uint32_t i = 0; i < 10; i++) { Vec_Push(array, (Obj*)Str_newf("%u32", i)); }
+ {
+ Vector *slice = Vec_Slice(array, 0, 10);
+ TEST_TRUE(runner, Vec_Equals(array, (Obj*)slice), "Slice entire array");
+ DECREF(slice);
+ }
+ {
+ Vector *slice = Vec_Slice(array, 0, 11);
+ TEST_TRUE(runner, Vec_Equals(array, (Obj*)slice),
+ "Exceed length");
+ DECREF(slice);
+ }
+ {
+ Vector *wanted = Vec_new(0);
+ Vec_Push(wanted, (Obj*)Str_newf("9"));
+ Vector *slice = Vec_Slice(array, 9, 11);
+ TEST_TRUE(runner, Vec_Equals(slice, (Obj*)wanted),
+ "Exceed length, start near end");
+ DECREF(slice);
+ DECREF(wanted);
+ }
+ {
+ Vector *slice = Vec_Slice(array, 0, 0);
+ TEST_TRUE(runner, Vec_Get_Size(slice) == 0, "empty slice");
+ DECREF(slice);
+ }
+ {
+ Vector *slice = Vec_Slice(array, 20, 1);
+ TEST_TRUE(runner, Vec_Get_Size(slice) == 0, "exceed offset");
+ DECREF(slice);
+ }
+ {
+ Vector *wanted = Vec_new(0);
+ Vec_Push(wanted, (Obj*)Str_newf("9"));
+ Vector *slice = Vec_Slice(array, 9, SIZE_MAX - 1);
+ TEST_TRUE(runner, Vec_Get_Size(slice) == 1, "guard against overflow");
+ DECREF(slice);
+ DECREF(wanted);
+ }
+ DECREF(array);
+}
+
+static void
+test_Clone(TestBatchRunner *runner) {
+ Vector *array = Vec_new(0);
+ Vector *twin;
+ uint32_t i;
+
+ for (i = 0; i < 10; i++) {
+ Vec_Push(array, (Obj*)Int_new(i));
+ }
+ Vec_Push(array, NULL);
+ twin = Vec_Clone(array);
+ TEST_TRUE(runner, Vec_Equals(array, (Obj*)twin), "Clone");
+ TEST_TRUE(runner, Vec_Fetch(array, 1) == Vec_Fetch(twin, 1),
+ "Clone doesn't clone elements");
+
+ DECREF(array);
+ DECREF(twin);
+}
+
+static void
+S_push(void *context) {
+ Vector *vec = (Vector*)context;
+ Vec_Push(vec, (Obj*)CFISH_TRUE);
+}
+
+static void
+S_insert_at_size_max(void *context) {
+ Vector *vec = (Vector*)context;
+ Vec_Insert(vec, SIZE_MAX, (Obj*)CFISH_TRUE);
+}
+
+static void
+S_store_at_size_max(void *context) {
+ Vector *vec = (Vector*)context;
+ Vec_Store(vec, SIZE_MAX, (Obj*)CFISH_TRUE);
+}
+
+typedef struct {
+ Vector *vec;
+ Vector *other;
+} VectorPair;
+
+static void
+S_push_all(void *vcontext) {
+ VectorPair *context = (VectorPair*)vcontext;
+ Vec_Push_All(context->vec, context->other);
+}
+
+static void
+S_insert_all_at_size_max(void *vcontext) {
+ VectorPair *context = (VectorPair*)vcontext;
+ Vec_Insert_All(context->vec, SIZE_MAX, context->other);
+}
+
+static void
+S_test_exception(TestBatchRunner *runner, Err_Attempt_t func, void *context,
+ const char *test_name) {
+ Err *error = Err_trap(func, context);
+ TEST_TRUE(runner, error != NULL, test_name);
+ DECREF(error);
+}
+
+static void
+test_exceptions(TestBatchRunner *runner) {
+ {
+ Vector *vec = Vec_new(0);
+ vec->cap = MAX_VECTOR_SIZE;
+ vec->size = vec->cap;
+ S_test_exception(runner, S_push, vec, "Push throws on overflow");
+ vec->size = 0;
+ DECREF(vec);
+ }
+
+ {
+ Vector *vec = Vec_new(0);
+ S_test_exception(runner, S_insert_at_size_max, vec,
+ "Insert throws on overflow");
+ DECREF(vec);
+ }
+
+ {
+ Vector *vec = Vec_new(0);
+ S_test_exception(runner, S_store_at_size_max, vec,
+ "Store throws on overflow");
+ DECREF(vec);
+ }
+
+ {
+ VectorPair context;
+ context.vec = Vec_new(0);
+ context.vec->cap = 1000000000;
+ context.vec->size = context.vec->cap;
+ context.other = Vec_new(0);
+ context.other->cap = MAX_VECTOR_SIZE - context.vec->cap + 1;
+ context.other->size = context.other->cap;
+ S_test_exception(runner, S_push_all, &context,
+ "Push_All throws on overflow");
+ context.vec->size = 0;
+ context.other->size = 0;
+ DECREF(context.other);
+ DECREF(context.vec);
+ }
+
+ {
+ VectorPair context;
+ context.vec = Vec_new(0);
+ context.other = Vec_new(0);
+ S_test_exception(runner, S_insert_all_at_size_max, &context,
+ "Insert_All throws on overflow");
+ DECREF(context.other);
+ DECREF(context.vec);
+ }
+}
+
+static void
+test_Sort(TestBatchRunner *runner) {
+ Vector *array = Vec_new(8);
+ Vector *wanted = Vec_new(8);
+
+ Vec_Push(array, NULL);
+ Vec_Push(array, (Obj*)Str_newf("aaab"));
+ Vec_Push(array, (Obj*)Str_newf("ab"));
+ Vec_Push(array, NULL);
+ Vec_Push(array, NULL);
+ Vec_Push(array, (Obj*)Str_newf("aab"));
+ Vec_Push(array, (Obj*)Str_newf("b"));
+
+ Vec_Push(wanted, (Obj*)Str_newf("aaab"));
+ Vec_Push(wanted, (Obj*)Str_newf("aab"));
+ Vec_Push(wanted, (Obj*)Str_newf("ab"));
+ Vec_Push(wanted, (Obj*)Str_newf("b"));
+ Vec_Push(wanted, NULL);
+ Vec_Push(wanted, NULL);
+ Vec_Push(wanted, NULL);
+
+ Vec_Sort(array);
+ TEST_TRUE(runner, Vec_Equals(array, (Obj*)wanted), "Sort with NULLs");
+
+ DECREF(array);
+ DECREF(wanted);
+}
+
+static void
+test_Grow(TestBatchRunner *runner) {
+ Vector *array = Vec_new(500);
+ size_t cap;
+
+ cap = Vec_Get_Capacity(array);
+ TEST_TRUE(runner, cap >= 500, "Array is created with minimum capacity");
+
+ Vec_Grow(array, 2000);
+ cap = Vec_Get_Capacity(array);
+ TEST_TRUE(runner, cap >= 2000, "Grow to larger capacity");
+
+ size_t old_cap = cap;
+ Vec_Grow(array, old_cap);
+ cap = Vec_Get_Capacity(array);
+ TEST_TRUE(runner, cap >= old_cap, "Grow to same capacity");
+
+ Vec_Grow(array, 1000);
+ cap = Vec_Get_Capacity(array);
+ TEST_TRUE(runner, cap >= 1000, "Grow to smaller capacity");
+
+ DECREF(array);
+}
+
+void
+TestVector_Run_IMP(TestVector *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 62);
+ test_Equals(runner);
+ test_Store_Fetch(runner);
+ test_Push_Pop_Insert(runner);
+ test_Insert_All(runner);
+ test_Delete(runner);
+ test_Resize(runner);
+ test_Excise(runner);
+ test_Push_All(runner);
+ test_Slice(runner);
+ test_Clone(runner);
+ test_exceptions(runner);
+ test_Sort(runner);
+ test_Grow(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/TestVector.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/TestVector.cfh b/runtime/test/Clownfish/Test/TestVector.cfh
new file mode 100644
index 0000000..090b8b9
--- /dev/null
+++ b/runtime/test/Clownfish/Test/TestVector.cfh
@@ -0,0 +1,29 @@
+/* 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::TestVector
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestVector*
+ new();
+
+ void
+ Run(TestVector *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/Util/TestAtomic.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/Util/TestAtomic.c b/runtime/test/Clownfish/Test/Util/TestAtomic.c
new file mode 100644
index 0000000..f87279a
--- /dev/null
+++ b/runtime/test/Clownfish/Test/Util/TestAtomic.c
@@ -0,0 +1,65 @@
+/* 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/TestHarness/TestBatchRunner.h"
+#include "Clownfish/Util/Atomic.h"
+#include "Clownfish/Class.h"
+
+TestAtomic*
+TestAtomic_new() {
+ return (TestAtomic*)Class_Make_Obj(TESTATOMIC);
+}
+
+static void
+test_cas_ptr(TestBatchRunner *runner) {
+ int foo = 1;
+ int bar = 2;
+ int *foo_pointer = &foo;
+ int *bar_pointer = &bar;
+ int *target = NULL;
+
+ TEST_TRUE(runner,
+ Atomic_cas_ptr((void**)&target, NULL, foo_pointer),
+ "cas_ptr returns true on success");
+ TEST_TRUE(runner, target == foo_pointer, "cas_ptr sets target");
+
+ target = NULL;
+ 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(runner, target == NULL,
+ "cas_ptr doesn't do anything to target when old_value doesn't match");
+
+ target = foo_pointer;
+ TEST_TRUE(runner,
+ Atomic_cas_ptr((void**)&target, foo_pointer, bar_pointer),
+ "cas_ptr from one value to another");
+ TEST_TRUE(runner, target == bar_pointer, "cas_ptr sets target");
+}
+
+void
+TestAtomic_Run_IMP(TestAtomic *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 6);
+ test_cas_ptr(runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/Util/TestAtomic.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/Util/TestAtomic.cfh b/runtime/test/Clownfish/Test/Util/TestAtomic.cfh
new file mode 100644
index 0000000..2788342
--- /dev/null
+++ b/runtime/test/Clownfish/Test/Util/TestAtomic.cfh
@@ -0,0 +1,29 @@
+/* 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::TestHarness::TestBatch {
+
+ inert incremented TestAtomic*
+ new();
+
+ void
+ Run(TestAtomic *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/Util/TestMemory.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/Util/TestMemory.c b/runtime/test/Clownfish/Test/Util/TestMemory.c
new file mode 100644
index 0000000..8151c72
--- /dev/null
+++ b/runtime/test/Clownfish/Test/Util/TestMemory.c
@@ -0,0 +1,119 @@
+/* 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 "charmony.h"
+
+#include "Clownfish/Test/Util/TestMemory.h"
+
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/Util/Memory.h"
+#include "Clownfish/Class.h"
+
+TestMemory*
+TestMemory_new() {
+ return (TestMemory*)Class_Make_Obj(TESTMEMORY);
+}
+
+static void
+test_oversize__growth_rate(TestBatchRunner *runner) {
+ 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(runner, "Asked for %" PRId64 ", got smaller amount %" PRId64,
+ size + 1, next_size);
+ break;
+ }
+ if (size > 0) {
+ growth_count += 1;
+ double growth_rate = CHY_U64_TO_DOUBLE(next_size) /
+ CHY_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(runner, "Average growth rate dropped below 1.1x: %f",
+ average_growth_rate);
+ success = false;
+ break;
+ }
+ }
+ size = next_size;
+ }
+ TEST_TRUE(runner, growth_count > 0, "Grew %f times", growth_count);
+ if (success) {
+ TEST_TRUE(runner, average_growth_rate > 1.1,
+ "Growth rate of oversize() averages above 1.1: %.3f",
+ average_growth_rate);
+ }
+
+ for (size_t minimum = 1; minimum < 8; minimum++) {
+ uint64_t next_size = Memory_oversize(minimum, sizeof(void*));
+ double growth_rate = CHY_U64_TO_DOUBLE(next_size) / (double)minimum;
+ TEST_TRUE(runner, growth_rate > 1.2,
+ "Growth rate is higher for smaller arrays (%u, %.3f)",
+ (unsigned)minimum, growth_rate);
+ }
+}
+
+static void
+test_oversize__ceiling(TestBatchRunner *runner) {
+ for (unsigned width = 0; width < 10; width++) {
+ size_t size = Memory_oversize(SIZE_MAX, width);
+ TEST_TRUE(runner, size == SIZE_MAX,
+ "Memory_oversize hits ceiling at SIZE_MAX (width %u)", width);
+ size = Memory_oversize(SIZE_MAX - 1, width);
+ TEST_TRUE(runner, size == SIZE_MAX,
+ "Memory_oversize hits ceiling at SIZE_MAX (width %u)", width);
+ }
+}
+
+static void
+test_oversize__rounding(TestBatchRunner *runner) {
+ unsigned widths[] = { 1, 2, 4, 0 };
+
+ for (int width_tick = 0; widths[width_tick] != 0; width_tick++) {
+ unsigned width = widths[width_tick];
+ for (unsigned i = 0; i < 25; i++) {
+ size_t size = Memory_oversize(i, width);
+ size_t bytes = size * width;
+ if (bytes % sizeof(size_t) != 0) {
+ FAIL(runner, "Rounding failure for %u, width %u",
+ i, width);
+ return;
+ }
+ }
+ }
+ PASS(runner, "Round allocations up to the size of a pointer");
+}
+
+void
+TestMemory_Run_IMP(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-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/Util/TestMemory.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/Util/TestMemory.cfh b/runtime/test/Clownfish/Test/Util/TestMemory.cfh
new file mode 100644
index 0000000..d0b5803
--- /dev/null
+++ b/runtime/test/Clownfish/Test/Util/TestMemory.cfh
@@ -0,0 +1,29 @@
+/* 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::TestHarness::TestBatch {
+
+ inert incremented TestMemory*
+ new();
+
+ void
+ Run(TestMemory *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/Util/TestStringHelper.c
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/Util/TestStringHelper.c b/runtime/test/Clownfish/Test/Util/TestStringHelper.c
new file mode 100644
index 0000000..2a873fd
--- /dev/null
+++ b/runtime/test/Clownfish/Test/Util/TestStringHelper.c
@@ -0,0 +1,373 @@
+/* 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/String.h"
+#include "Clownfish/Err.h"
+#include "Clownfish/Test.h"
+#include "Clownfish/TestHarness/TestBatchRunner.h"
+#include "Clownfish/Util/StringHelper.h"
+#include "Clownfish/Class.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() {
+ return (TestStringHelper*)Class_Make_Obj(TESTSTRINGHELPER);
+}
+
+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(TestBatchRunner *runner) {
+ size_t result;
+ result = StrHelp_overlap("", "", 0, 0);
+ TEST_UINT_EQ(runner, result, 0, "two empty strings");
+ result = StrHelp_overlap("", "foo", 0, 3);
+ TEST_UINT_EQ(runner, result, 0, "first string is empty");
+ result = StrHelp_overlap("foo", "", 3, 0);
+ TEST_UINT_EQ(runner, result, 0, "second string is empty");
+ result = StrHelp_overlap("foo", "foo", 3, 3);
+ TEST_UINT_EQ(runner, result, 3, "equal strings");
+ result = StrHelp_overlap("foo bar", "foo", 7, 3);
+ TEST_UINT_EQ(runner, result, 3, "first string is longer");
+ result = StrHelp_overlap("foo", "foo bar", 3, 7);
+ TEST_UINT_EQ(runner, result, 3, "second string is longer");
+ result = StrHelp_overlap("bar", "baz", 3, 3);
+ TEST_UINT_EQ(runner, result, 2, "different byte");
+}
+
+
+static void
+test_to_base36(TestBatchRunner *runner) {
+ char buffer[StrHelp_MAX_BASE36_BYTES];
+ StrHelp_to_base36(UINT64_MAX, buffer);
+ TEST_STR_EQ(runner, "3w5e11264sgsf", buffer, "base36 UINT64_MAX");
+ StrHelp_to_base36(1, buffer);
+ TEST_STR_EQ(runner, "1", buffer, "base36 1");
+ TEST_INT_EQ(runner, buffer[1], 0, "base36 NULL termination");
+}
+
+static void
+test_utf8_round_trip(TestBatchRunner *runner) {
+ int32_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(runner, "Successfully round tripped 0 - 0x10FFFF");
+ }
+ else {
+ FAIL(runner, "Failed round trip at 0x%.1X", (unsigned)code_point);
+ }
+}
+
+static void
+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(runner, "Disagreement: %s", description);
+ }
+ else {
+ TEST_TRUE(runner, sane == expected, "%s", description);
+ }
+}
+
+static void
+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(runner, "\xF0\x9D\x84\x9E", 4, true,
+ "Musical symbol G clef");
+ S_test_validity(runner, "\xED\xA0\xB4\xED\xB4\x9E", 6, false,
+ "G clef as UTF-8 encoded UTF-16 surrogates");
+ S_test_validity(runner, ".\xED\xA0\xB4.", 5, false,
+ "Isolated high surrogate");
+ S_test_validity(runner, ".\xED\xB4\x9E.", 5, false,
+ "Isolated low surrogate");
+
+ // Shortest form.
+ S_test_validity(runner, ".\xC1\x9C.", 4, false,
+ "Non-shortest form ASCII backslash");
+ S_test_validity(runner, ".\xC0\xAF.", 4, false,
+ "Non-shortest form ASCII slash");
+ S_test_validity(runner, ".\xC0\x80.", 4, false,
+ "Non-shortest form ASCII NUL character");
+ S_test_validity(runner, ".\xE0\x9F\xBF.", 5, false,
+ "Non-shortest form three byte sequence");
+ S_test_validity(runner, ".\xF0\x8F\xBF\xBF.", 6, false,
+ "Non-shortest form four byte sequence");
+
+ // Range.
+ S_test_validity(runner, "\xF8\x88\x80\x80\x80", 5, false, "5-byte UTF-8");
+ S_test_validity(runner, "\xF4\x8F\xBF\xBF", 4, true,
+ "Code point 0x10FFFF");
+ S_test_validity(runner, "\xF4\x90\x80\x80", 4, false,
+ "Code point 0x110000 too large");
+ S_test_validity(runner, "\xF5\x80\x80\x80", 4, false,
+ "Sequence starting with 0xF5");
+
+ // Truncated sequences.
+ S_test_validity(runner, "\xC2", 1, false,
+ "Truncated two byte sequence");
+ S_test_validity(runner, "\xE2\x98", 2, false,
+ "Truncated three byte sequence");
+ S_test_validity(runner, "\xF0\x9D\x84", 3, false,
+ "Truncated four byte sequence");
+
+ // Bad continuations.
+ S_test_validity(runner, "\xE2\x98\xBA\xE2\x98\xBA", 6, true,
+ "SmileySmiley");
+ S_test_validity(runner, "\xE2\xBA\xE2\x98\xBA", 5, false,
+ "missing first continuation byte");
+ S_test_validity(runner, "\xE2\x98\xE2\x98\xBA", 5, false,
+ "missing second continuation byte");
+ S_test_validity(runner, "\xE2\xE2\x98\xBA", 4, false,
+ "missing both continuation bytes");
+ S_test_validity(runner, "\xBA\xE2\x98\xBA\xE2\xBA", 5, false,
+ "missing first continuation byte (end)");
+ S_test_validity(runner, "\xE2\x98\xBA\xE2\x98", 5, false,
+ "missing second continuation byte (end)");
+ S_test_validity(runner, "\xE2\x98\xBA\xE2", 4, false,
+ "missing both continuation bytes (end)");
+ S_test_validity(runner, "\xBA\xE2\x98\xBA", 4, false,
+ "isolated continuation byte 0xBA");
+ S_test_validity(runner, "\x98\xE2\x98\xBA", 4, false,
+ "isolated continuation byte 0x98");
+ S_test_validity(runner, "\xE2\x98\xBA\xBA", 4, false,
+ "isolated continuation byte 0xBA (end)");
+ S_test_validity(runner, "\xE2\x98\xBA\x98", 4, false,
+ "isolated continuation byte 0x98 (end)");
+ S_test_validity(runner, "\xF0xxxx", 5, false,
+ "missing continuation byte 2/4");
+ S_test_validity(runner, "\xF0\x9Dxxxx", 5, false,
+ "missing continuation byte 3/4");
+ S_test_validity(runner, "\xF0\x9D\x84xx", 5, false,
+ "missing continuation byte 4/4");
+}
+
+static void
+S_validate_utf8(void *context) {
+ const char *text = (const char*)context;
+ StrHelp_validate_utf8(text, strlen(text), "src.c", 17, "fn");
+}
+
+static void
+test_validate_utf8(TestBatchRunner *runner) {
+ {
+ Err *error = Err_trap(S_validate_utf8, "Sigma\xC1\x9C.");
+ TEST_TRUE(runner, error != NULL, "validate_utf8 throws");
+ String *mess = Err_Get_Mess(error);
+ const char *expected = "Invalid UTF-8 after 'Sigma': C1 9C 2E\n";
+ bool ok = Str_Starts_With_Utf8(mess, expected, strlen(expected));
+ TEST_TRUE(runner, ok, "validate_utf8 throws correct error message");
+ DECREF(error);
+ }
+
+ {
+ Err *error = Err_trap(S_validate_utf8,
+ "xxx123456789\xE2\x93\xAA"
+ "1234567890\xC1\x9C.");
+ String *mess = Err_Get_Mess(error);
+ const char *expected =
+ "Invalid UTF-8 after '123456789\xE2\x93\xAA"
+ "1234567890': C1 9C 2E\n";
+ bool ok = Str_Starts_With_Utf8(mess, expected, strlen(expected));
+ TEST_TRUE(runner, ok, "validate_utf8 truncates long prefix");
+ DECREF(error);
+ }
+}
+
+static void
+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_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
+S_encode_utf8_char(void *context) {
+ int32_t *code_point_ptr = (int32_t*)context;
+ char buffer[4];
+ StrHelp_encode_utf8_char(*code_point_ptr, buffer);
+}
+
+static void
+test_encode_utf8_char(TestBatchRunner *runner) {
+ int32_t code_point = 0x110000;
+ Err *error = Err_trap(S_encode_utf8_char, &code_point);
+ TEST_TRUE(runner, error != NULL, "Encode code point 0x110000 throws");
+ DECREF(error);
+}
+
+static void
+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(runner, StrHelp_back_utf8_char(end, buffer) == buffer,
+ "back_utf8_char");
+ TEST_TRUE(runner, StrHelp_back_utf8_char(end, buf) == NULL,
+ "back_utf8_char returns NULL rather than back up beyond start");
+ TEST_TRUE(runner, StrHelp_back_utf8_char(buffer, buffer) == NULL,
+ "back_utf8_char returns NULL when end == start");
+}
+
+void
+TestStrHelp_Run_IMP(TestStringHelper *self, TestBatchRunner *runner) {
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 55);
+ test_overlap(runner);
+ test_to_base36(runner);
+ test_utf8_round_trip(runner);
+ test_utf8_valid(runner);
+ test_validate_utf8(runner);
+ test_is_whitespace(runner);
+ test_encode_utf8_char(runner);
+ test_back_utf8_char(runner);
+}
+
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/Clownfish/Test/Util/TestStringHelper.cfh
----------------------------------------------------------------------
diff --git a/runtime/test/Clownfish/Test/Util/TestStringHelper.cfh b/runtime/test/Clownfish/Test/Util/TestStringHelper.cfh
new file mode 100644
index 0000000..752c553
--- /dev/null
+++ b/runtime/test/Clownfish/Test/Util/TestStringHelper.cfh
@@ -0,0 +1,29 @@
+/* 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 nickname TestStrHelp
+ inherits Clownfish::TestHarness::TestBatch {
+
+ inert incremented TestStringHelper*
+ new();
+
+ void
+ Run(TestStringHelper *self, TestBatchRunner *runner);
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/TestClownfish.c
----------------------------------------------------------------------
diff --git a/runtime/test/TestClownfish.c b/runtime/test/TestClownfish.c
new file mode 100644
index 0000000..e9ec7a3
--- /dev/null
+++ b/runtime/test/TestClownfish.c
@@ -0,0 +1,22 @@
+/* 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 "testcfish_parcel.h"
+
+void
+testcfish_init_parcel() {
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ba4e619/runtime/test/TestClownfish.cfp
----------------------------------------------------------------------
diff --git a/runtime/test/TestClownfish.cfp b/runtime/test/TestClownfish.cfp
new file mode 100644
index 0000000..6db4b4a
--- /dev/null
+++ b/runtime/test/TestClownfish.cfp
@@ -0,0 +1,8 @@
+{
+ "name": "TestClownfish",
+ "nickname": "TestCfish",
+ "version": "v0.5.0",
+ "prerequisites": {
+ "Clownfish": "v0.5.0"
+ }
+}
[03/14] lucy-clownfish git commit: Make some internal symbols visible
Posted by nw...@apache.org.
Make some internal symbols visible
Otherwise the separate test binary can't see them.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/83c90450
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/83c90450
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/83c90450
Branch: refs/heads/master
Commit: 83c9045079e5e5e21b487feaaeb5a506108b24b3
Parents: 8ba4e61
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 8 13:57:18 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 8 14:25:36 2016 +0200
----------------------------------------------------------------------
runtime/core/Clownfish/LockFreeRegistry.h | 10 ++++++----
runtime/core/Clownfish/PtrHash.h | 10 ++++++----
runtime/core/Clownfish/Util/Atomic.h | 4 ++--
3 files changed, 14 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/83c90450/runtime/core/Clownfish/LockFreeRegistry.h
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/LockFreeRegistry.h b/runtime/core/Clownfish/LockFreeRegistry.h
index 065c8bf..ac2f74d 100644
--- a/runtime/core/Clownfish/LockFreeRegistry.h
+++ b/runtime/core/Clownfish/LockFreeRegistry.h
@@ -19,6 +19,8 @@
#include <stddef.h>
+#include "cfish_parcel.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -31,17 +33,17 @@ struct cfish_String;
typedef struct cfish_LockFreeRegistry cfish_LockFreeRegistry;
-cfish_LockFreeRegistry*
+CFISH_VISIBLE cfish_LockFreeRegistry*
cfish_LFReg_new(size_t capacity);
-void
+CFISH_VISIBLE void
cfish_LFReg_destroy(cfish_LockFreeRegistry *self);
-bool
+CFISH_VISIBLE bool
cfish_LFReg_register(cfish_LockFreeRegistry *self, struct cfish_String *key,
struct cfish_Obj *value);
-struct cfish_Obj*
+CFISH_VISIBLE struct cfish_Obj*
cfish_LFReg_fetch(cfish_LockFreeRegistry *self, struct cfish_String *key);
#ifdef CFISH_USE_SHORT_NAMES
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/83c90450/runtime/core/Clownfish/PtrHash.h
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/PtrHash.h b/runtime/core/Clownfish/PtrHash.h
index 4a88bc4..03d5f95 100644
--- a/runtime/core/Clownfish/PtrHash.h
+++ b/runtime/core/Clownfish/PtrHash.h
@@ -19,22 +19,24 @@
#include <stddef.h>
+#include "cfish_parcel.h"
+
#ifdef __cplusplus
extern "C" {
#endif
typedef struct cfish_PtrHash cfish_PtrHash;
-cfish_PtrHash*
+CFISH_VISIBLE cfish_PtrHash*
cfish_PtrHash_new(size_t min_cap);
-void
+CFISH_VISIBLE void
CFISH_PtrHash_Destroy(cfish_PtrHash *self);
-void
+CFISH_VISIBLE void
CFISH_PtrHash_Store(cfish_PtrHash *self, void *key, void *value);
-void*
+CFISH_VISIBLE void*
CFISH_PtrHash_Fetch(cfish_PtrHash *self, void *key);
#ifdef CFISH_USE_SHORT_NAMES
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/83c90450/runtime/core/Clownfish/Util/Atomic.h
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Util/Atomic.h b/runtime/core/Clownfish/Util/Atomic.h
index 8b2f8e6..88d8de9 100644
--- a/runtime/core/Clownfish/Util/Atomic.h
+++ b/runtime/core/Clownfish/Util/Atomic.h
@@ -57,7 +57,7 @@ cfish_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {
/********************************** Windows *******************************/
#elif defined(CHY_HAS_WINDOWS_H)
-bool
+CFISH_VISIBLE bool
cfish_Atomic_wrapped_cas_ptr(void *volatile *target, void *old_value,
void *new_value);
@@ -87,7 +87,7 @@ cfish_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 cfish_Atomic_mutex;
+extern CFISH_VISIBLE pthread_mutex_t cfish_Atomic_mutex;
static CFISH_INLINE bool
cfish_Atomic_cas_ptr(void *volatile *target, void *old_value, void *new_value) {