Updated Branches:
  refs/heads/cfc-tests 3a9cef14e -> 64602a2a9

Port more CFC tests to C


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

Branch: refs/heads/cfc-tests
Commit: 64602a2a992b205600ec40d6ea39822635cee52e
Parents: 3a9cef1
Author: Nick Wellnhofer <[email protected]>
Authored: Mon Jan 28 23:02:59 2013 +0100
Committer: Nick Wellnhofer <[email protected]>
Committed: Tue Jan 29 02:21:31 2013 +0100

----------------------------------------------------------------------
 clownfish/compiler/perl/lib/Clownfish/CFC.xs    |   14 +-
 clownfish/compiler/perl/t/core/300-variable.t   |   23 ++
 clownfish/compiler/perl/t/core/301-param_list.t |   23 ++
 clownfish/compiler/perl/t/core/400-file_spec.t  |   23 ++
 clownfish/compiler/perl/t/core/401-class.t      |   23 ++
 clownfish/compiler/src/CFCTest.c                |   43 ++-
 clownfish/compiler/src/CFCTest.h                |   22 ++
 clownfish/compiler/src/CFCTestClass.c           |  352 ++++++++++++++++++
 clownfish/compiler/src/CFCTestFileSpec.c        |   54 +++
 clownfish/compiler/src/CFCTestParamList.c       |   78 ++++
 clownfish/compiler/src/CFCTestVariable.c        |  101 +++++
 11 files changed, 740 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC.xs 
b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
index c461922..fc306f2 100644
--- a/clownfish/compiler/perl/lib/Clownfish/CFC.xs
+++ b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
@@ -2406,21 +2406,33 @@ run_batch(self, klass)
     CFCTest *self;
     const char *klass;
 PPCODE:
-    if (strcmp(klass, "Clownfish::CFC::Model::DocuComment") == 0) {
+    if (strcmp(klass, "Clownfish::CFC::Model::Class") == 0) {
+        CFCTestClass_run(self);
+    }
+    else if (strcmp(klass, "Clownfish::CFC::Model::DocuComment") == 0) {
         CFCTestDocuComment_run(self);
     }
+    else if (strcmp(klass, "Clownfish::CFC::Model::FileSpec") == 0) {
+        CFCTestFileSpec_run(self);
+    }
     else if (strcmp(klass, "Clownfish::CFC::Model::Function") == 0) {
         CFCTestFunction_run(self);
     }
     else if (strcmp(klass, "Clownfish::CFC::Model::Method") == 0) {
         CFCTestMethod_run(self);
     }
+    else if (strcmp(klass, "Clownfish::CFC::Model::ParamList") == 0) {
+        CFCTestParamList_run(self);
+    }
     else if (strcmp(klass, "Clownfish::CFC::Model::Symbol") == 0) {
         CFCTestSymbol_run(self);
     }
     else if (strcmp(klass, "Clownfish::CFC::Model::Type") == 0) {
         CFCTestType_run(self);
     }
+    else if (strcmp(klass, "Clownfish::CFC::Model::Variable") == 0) {
+        CFCTestVariable_run(self);
+    }
     else if (strcmp(klass, "Clownfish::CFC::Model::Version") == 0) {
         CFCTestVersion_run(self);
     }

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/t/core/300-variable.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/300-variable.t 
b/clownfish/compiler/perl/t/core/300-variable.t
new file mode 100644
index 0000000..9e0e1ed
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/300-variable.t
@@ -0,0 +1,23 @@
+# 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.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+$test->run_batch('Clownfish::CFC::Model::Variable');
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/t/core/301-param_list.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/301-param_list.t 
b/clownfish/compiler/perl/t/core/301-param_list.t
new file mode 100644
index 0000000..66abb5e
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/301-param_list.t
@@ -0,0 +1,23 @@
+# 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.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+$test->run_batch('Clownfish::CFC::Model::ParamList');
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/t/core/400-file_spec.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/400-file_spec.t 
b/clownfish/compiler/perl/t/core/400-file_spec.t
new file mode 100644
index 0000000..46e34c4
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/400-file_spec.t
@@ -0,0 +1,23 @@
+# 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.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+$test->run_batch('Clownfish::CFC::Model::FileSpec');
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/perl/t/core/401-class.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/401-class.t 
b/clownfish/compiler/perl/t/core/401-class.t
new file mode 100644
index 0000000..f78e107
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/401-class.t
@@ -0,0 +1,23 @@
+# 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.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+$test->run_batch('Clownfish::CFC::Model::Class');
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTest.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTest.c b/clownfish/compiler/src/CFCTest.c
index 0085aa9..352cdd1 100644
--- a/clownfish/compiler/src/CFCTest.c
+++ b/clownfish/compiler/src/CFCTest.c
@@ -22,12 +22,7 @@
 #define CFC_USE_TEST_MACROS
 #include "CFCTest.h"
 #include "CFCBase.h"
-#include "CFCFunction.h"
-#include "CFCMethod.h"
-#include "CFCParamList.h"
-#include "CFCParcel.h"
 #include "CFCParser.h"
-#include "CFCType.h"
 #include "CFCUtil.h"
 
 struct CFCTestFormatter {
@@ -352,48 +347,66 @@ static void
 S_format_tap_summary(CFCTest *test) {
 }
 
-CFCParcel*
+struct CFCParcel*
 CFCTest_parse_parcel(CFCTest *test, CFCParser *parser, const char *src) {
     CFCBase *result = CFCParser_parse(parser, src);
     OK(test, result != NULL, "parse '%s'", src);
     STR_EQ(test, CFCBase_get_cfc_class(result),
            "Clownfish::CFC::Model::Parcel", "result class of '%s'", src);
-    return (CFCParcel*)result;
+    return (struct CFCParcel*)result;
 }
 
-CFCType*
+struct CFCType*
 CFCTest_parse_type(CFCTest *test, CFCParser *parser, const char *src) {
     CFCBase *result = CFCParser_parse(parser, src);
     OK(test, result != NULL, "parse '%s'", src);
     STR_EQ(test, CFCBase_get_cfc_class(result),
            "Clownfish::CFC::Model::Type", "result class of '%s'", src);
-    return (CFCType*)result;
+    return (struct CFCType*)result;
 }
 
-CFCParamList*
+struct CFCVariable*
+CFCTest_parse_variable(CFCTest *test, CFCParser *parser, const char *src) {
+    CFCBase *result = CFCParser_parse(parser, src);
+    OK(test, result != NULL, "parse '%s'", src);
+    STR_EQ(test, CFCBase_get_cfc_class(result),
+           "Clownfish::CFC::Model::Variable", "result class of '%s'", src);
+    return (struct CFCVariable*)result;
+}
+
+struct CFCParamList*
 CFCTest_parse_param_list(CFCTest *test, CFCParser *parser, const char *src) {
     CFCBase *result = CFCParser_parse(parser, src);
     OK(test, result != NULL, "parse '%s'", src);
     STR_EQ(test, CFCBase_get_cfc_class(result),
            "Clownfish::CFC::Model::ParamList", "result class of '%s'", src);
-    return (CFCParamList*)result;
+    return (struct CFCParamList*)result;
 }
 
-CFCFunction*
+struct CFCFunction*
 CFCTest_parse_function(CFCTest *test, CFCParser *parser, const char *src) {
     CFCBase *result = CFCParser_parse(parser, src);
     OK(test, result != NULL, "parse '%s'", src);
     STR_EQ(test, CFCBase_get_cfc_class(result),
            "Clownfish::CFC::Model::Function", "result class of '%s'", src);
-    return (CFCFunction*)result;
+    return (struct CFCFunction*)result;
 }
 
-CFCMethod*
+struct CFCMethod*
 CFCTest_parse_method(CFCTest *test, CFCParser *parser, const char *src) {
     CFCBase *result = CFCParser_parse(parser, src);
     OK(test, result != NULL, "parse '%s'", src);
     STR_EQ(test, CFCBase_get_cfc_class(result),
            "Clownfish::CFC::Model::Method", "result class of '%s'", src);
-    return (CFCMethod*)result;
+    return (struct CFCMethod*)result;
+}
+
+struct CFCClass*
+CFCTest_parse_class(CFCTest *test, CFCParser *parser, const char *src) {
+    CFCBase *result = CFCParser_parse(parser, src);
+    OK(test, result != NULL, "parse class");
+    STR_EQ(test, CFCBase_get_cfc_class(result),
+           "Clownfish::CFC::Model::Class", "result class");
+    return (struct CFCClass*)result;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTest.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTest.h b/clownfish/compiler/src/CFCTest.h
index cf8f3ac..ecada06 100644
--- a/clownfish/compiler/src/CFCTest.h
+++ b/clownfish/compiler/src/CFCTest.h
@@ -24,11 +24,14 @@
 #endif
 
 typedef struct CFCTest CFCTest;
+struct CFCClass;
 struct CFCFunction;
+struct CFCMethod;
 struct CFCParamList;
 struct CFCParcel;
 struct CFCParser;
 struct CFCType;
+struct CFCVariable;
 
 CFCTest*
 CFCTest_new(const char *formatter_name);
@@ -65,6 +68,10 @@ CFCTest_parse_parcel(CFCTest *test, struct CFCParser 
*parser, const char *src);
 struct CFCType*
 CFCTest_parse_type(CFCTest *test, struct CFCParser *parser, const char *src);
 
+struct CFCVariable*
+CFCTest_parse_variable(CFCTest *test, struct CFCParser *parser,
+                       const char *src);
+
 struct CFCParamList*
 CFCTest_parse_param_list(CFCTest *test, struct CFCParser *parser,
                          const char *src);
@@ -76,16 +83,28 @@ CFCTest_parse_function(CFCTest *test, struct CFCParser 
*parser,
 struct CFCMethod*
 CFCTest_parse_method(CFCTest *test, struct CFCParser *parser, const char *src);
 
+struct CFCClass*
+CFCTest_parse_class(CFCTest *test, struct CFCParser *parser, const char *src);
+
+void
+CFCTestClass_run(CFCTest *test);
+
 void
 CFCTestDocuComment_run(CFCTest *test);
 
 void
+CFCTestFileSpec_run(CFCTest *test);
+
+void
 CFCTestFunction_run(CFCTest *test);
 
 void
 CFCTestMethod_run(CFCTest *test);
 
 void
+CFCTestParamList_run(CFCTest *test);
+
+void
 CFCTestSymbol_run(CFCTest *test);
 
 void
@@ -95,6 +114,9 @@ void
 CFCTestUtil_run(CFCTest *test);
 
 void
+CFCTestVariable_run(CFCTest *test);
+
+void
 CFCTestVersion_run(CFCTest *test);
 
 #endif /* H_TEST_CFC */

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTestClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestClass.c 
b/clownfish/compiler/src/CFCTestClass.c
new file mode 100644
index 0000000..50b4024
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestClass.c
@@ -0,0 +1,352 @@
+/* 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 CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCClass.h"
+#include "CFCFileSpec.h"
+#include "CFCFunction.h"
+#include "CFCMethod.h"
+#include "CFCParamList.h"
+#include "CFCParcel.h"
+#include "CFCParser.h"
+#include "CFCSymbol.h"
+#include "CFCTest.h"
+#include "CFCType.h"
+#include "CFCUtil.h"
+#include "CFCVariable.h"
+
+static void
+S_run_basic_tests(CFCTest *test);
+
+static int
+S_has_symbol(CFCSymbol **symbols, const char *micro_sym);
+
+void
+CFCTestClass_run(CFCTest *test) {
+    CFCTest_start_batch(test, "class", 83);
+
+    S_run_basic_tests(test);
+}
+
+static void
+S_run_basic_tests(CFCTest *test) {
+    CFCParser *parser = CFCParser_new();
+
+    CFCParcel *neato = CFCParcel_new("Neato", NULL, NULL);
+    CFCFileSpec *file_spec = CFCFileSpec_new(".", "Foo/FooJr", 0);
+
+    CFCVariable *thing;
+    CFCVariable *widget;
+    CFCFunction *tread_water;
+
+    {
+        CFCType *thing_type = CFCTest_parse_type(test, parser, "Thing*");
+        thing = CFCVariable_new(neato, NULL, "Foo", NULL, "thing",
+                                thing_type, 0);
+
+        CFCType *widget_type = CFCTest_parse_type(test, parser, "Widget*");
+        widget = CFCVariable_new(NULL, NULL, "Widget", NULL, "widget",
+                                 widget_type, 0);
+
+        CFCType *return_type = CFCTest_parse_type(test, parser, "void");
+        CFCParamList *param_list
+            = CFCTest_parse_param_list(test, parser, "()");
+        tread_water
+            = CFCFunction_new(neato, NULL, "Foo", NULL, "tread_water",
+                              return_type, param_list, NULL, 0);
+
+        CFCBase_decref((CFCBase*)thing_type);
+        CFCBase_decref((CFCBase*)widget_type);
+        CFCBase_decref((CFCBase*)return_type);
+        CFCBase_decref((CFCBase*)param_list);
+    }
+
+    CFCClass *foo
+        = CFCClass_create(neato, NULL, "Foo", NULL, NULL, NULL, NULL, NULL,
+                          0, 0);
+    CFCClass_add_function(foo, tread_water);
+    CFCClass_add_member_var(foo, thing);
+    CFCClass_add_inert_var(foo, widget);
+
+    {
+        CFCClass *should_be_foo = CFCClass_fetch_singleton(neato, "Foo");
+        OK(test, should_be_foo == foo, "fetch_singleton");
+        CFCBase_decref((CFCBase*)should_be_foo);
+    }
+
+    CFCClass *foo_jr
+        = CFCClass_create(neato, NULL, "Foo::FooJr", NULL, NULL, NULL, NULL,
+                          "Foo", 0, 0);
+    CFCClass_add_attribute(foo_jr, "dumpable", "1");
+    OK(test, CFCClass_has_attribute(foo_jr, "dumpable"), "has_attribute");
+    STR_EQ(test, CFCClass_get_struct_sym(foo_jr), "FooJr",
+           "get_struct_sym");
+    STR_EQ(test, CFCClass_full_struct_sym(foo_jr), "neato_FooJr",
+           "full_struct_sym");
+
+    CFCClass *final_foo
+        = CFCClass_create(neato, NULL, "Foo::FooJr::FinalFoo", NULL, NULL, 
NULL,
+                          file_spec, "Foo::FooJr", 1, 0);
+    CFCClass_add_attribute(final_foo, "dumpable", "1");
+    OK(test, CFCClass_final(final_foo), "final");
+    STR_EQ(test, CFCClass_include_h(final_foo), "Foo/FooJr.h",
+           "include_h uses path_part");
+    STR_EQ(test, CFCClass_get_parent_class_name(final_foo), "Foo::FooJr",
+           "get_parent_class_name");
+
+    {
+        CFCParcel *parsed_neato
+            = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+        CFCBase_decref((CFCBase*)parsed_neato);
+    }
+
+    CFCParser_set_class_name(parser, "Foo");
+    CFCMethod *do_stuff
+        = CFCTest_parse_method(test, parser, "void Do_Stuff(Foo *self);");
+    CFCClass_add_method(foo, do_stuff);
+
+    CFCClass_add_child(foo, foo_jr);
+    CFCClass_add_child(foo_jr, final_foo);
+    CFCClass_grow_tree(foo);
+
+    OK(test, CFCClass_get_parent(foo_jr) == foo, "grow_tree, one level" );
+    OK(test, CFCClass_get_parent(final_foo) == foo_jr,
+       "grow_tree, two levels");
+    OK(test, CFCClass_fresh_method(foo, "Do_Stuff") == do_stuff,
+       "fresh_method");
+    OK(test, CFCClass_method(foo_jr, "Do_Stuff") == do_stuff,
+       "inherited method");
+    OK(test, CFCClass_fresh_method(foo_jr, "Do_Stuff") == NULL,
+       "inherited method not 'fresh'");
+    OK(test, CFCMethod_final(CFCClass_method(final_foo, "Do_Stuff")),
+       "Finalize inherited method");
+    OK(test, !CFCMethod_final(CFCClass_method(foo_jr, "Do_Stuff")),
+       "Don't finalize method in parent");
+
+    {
+        CFCVariable **inert_vars = CFCClass_inert_vars(foo);
+        OK(test, inert_vars[0] == widget, "inert_vars[0]");
+        OK(test, inert_vars[1] == NULL, "inert_vars[1]");
+
+        CFCFunction **functions = CFCClass_functions(foo);
+        OK(test, functions[0] == tread_water, "functions[0]");
+        OK(test, functions[1] == NULL, "functions[1]");
+
+        CFCMethod **methods = CFCClass_methods(foo);
+        OK(test, methods[0] == do_stuff, "methods[0]");
+        OK(test, methods[1] == NULL, "methods[1]");
+
+        CFCMethod **fresh_methods = CFCClass_fresh_methods(foo);
+        OK(test, fresh_methods[0] == do_stuff, "fresh_methods[0]");
+        OK(test, fresh_methods[1] == NULL, "fresh_methods[1]");
+
+        CFCVariable **fresh_member_vars = CFCClass_fresh_member_vars(foo);
+        OK(test, fresh_member_vars[0] == thing, "fresh_member_vars[0]");
+        OK(test, fresh_member_vars[1] == NULL, "fresh_member_vars[1]");
+    }
+
+    {
+        CFCVariable **member_vars = CFCClass_member_vars(foo_jr);
+        OK(test, member_vars[0] == thing, "member_vars[0]");
+        OK(test, member_vars[1] == NULL, "member_vars[1]");
+
+        CFCFunction **functions = CFCClass_functions(foo_jr);
+        OK(test, functions[0] == NULL, "functions[0]");
+
+        CFCVariable **fresh_member_vars = CFCClass_fresh_member_vars(foo_jr);
+        OK(test, fresh_member_vars[0] == NULL, "fresh_member_vars[0]");
+
+        CFCVariable **inert_vars = CFCClass_inert_vars(foo_jr);
+        OK(test, inert_vars[0] == NULL, "inert_vars[0]");
+    }
+
+    {
+        CFCMethod **fresh_methods = CFCClass_fresh_methods(final_foo);
+        OK(test, fresh_methods[0] == NULL, "fresh_methods[0]");
+    }
+
+    {
+        const char *autocode = CFCClass_get_autocode(foo_jr);
+        OK(test, strstr(autocode, "load") != NULL, "autogenerate Dump/Load");
+    }
+
+    {
+        CFCClass **ladder = CFCClass_tree_to_ladder(foo);
+        OK(test, ladder[0] == foo, "ladder[0]");
+        OK(test, ladder[1] == foo_jr, "ladder[1]");
+        OK(test, ladder[2] == final_foo, "ladder[2]");
+        OK(test, ladder[3] == NULL, "ladder[3]");
+    }
+
+    {
+        CFCClass *final_class
+            = CFCTest_parse_class(test, parser, "final class Iamfinal { }");
+        OK(test, CFCClass_final(final_class), "class modifer: final");
+        CFCClass *inert_class
+            = CFCTest_parse_class(test, parser, "inert class Iaminert { }");
+        OK(test, CFCClass_inert(inert_class), "class modifer: inert");
+
+        CFCBase_decref((CFCBase*)final_class);
+        CFCBase_decref((CFCBase*)inert_class);
+    }
+
+    {
+        static const char *names[2] = { "Fooble", "Foo::FooJr::FooIII" };
+        for (int i = 0; i < 2; ++i) {
+            const char *name = names[i];
+            char *class_src
+                = CFCUtil_sprintf("class Fu::%s inherits %s { }", name, name);
+            CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+            STR_EQ(test, CFCClass_get_parent_class_name(klass), name,
+                   "class_inheritance: %s", name);
+            FREEMEM(class_src);
+            CFCBase_decref((CFCBase*)klass);
+        }
+    }
+
+    {
+        const char *class_src =
+            "public class Foo::Foodie cnick Foodie inherits Foo {\n"
+            "    private int num;\n"
+            "}\n";
+        CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+        CFCSymbol **member_vars = (CFCSymbol**)CFCClass_member_vars(klass);
+        OK(test, S_has_symbol(member_vars, "num"),
+           "parsed private member var");
+
+        CFCBase_decref((CFCBase*)klass);
+    }
+
+    {
+        const char *class_src =
+            "/**\n"
+            " * Bow wow.\n"
+            " *\n"
+            " * Wow wow wow.\n"
+            " */\n"
+            "public class Animal::Dog inherits Animal : lovable : drooly {\n"
+            "    public inert Dog* init(Dog *self, CharBuf *name,\n"
+            "                           CharBuf *fave_food);\n"
+            "    inert uint32_t count();\n"
+            "    inert uint64_t num_dogs;\n"
+            "\n"
+            "    private CharBuf *name;\n"
+            "    private bool     likes_to_go_fetch;\n"
+            "    private void     Chase_Tail(Dog *self);\n"
+            "\n"
+            "    ChewToy *squishy;\n"
+            "\n"
+            "    void               Destroy(Dog *self);\n"
+            "    public CharBuf*    Bark(Dog *self);\n"
+            "    public void        Eat(Dog *self);\n"
+            "    public void        Bite(Dog *self, Enemy *enemy);\n"
+            "    public Thing      *Fetch(Dog *self, Thing *thing);\n"
+            "    public final void  Bury(Dog *self, Bone *bone);\n"
+            "    public Owner      *mom;\n"
+            "    public abstract incremented nullable Thing*\n"
+            "    Scratch(Dog *self);\n"
+            "\n"
+            "    int32_t[1]  flexible_array_at_end_of_struct;\n"
+            "}\n";
+        CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+
+        CFCSymbol **inert_vars  = (CFCSymbol**)CFCClass_inert_vars(klass);
+        CFCSymbol **member_vars = (CFCSymbol**)CFCClass_member_vars(klass);
+        CFCSymbol **functions   = (CFCSymbol**)CFCClass_functions(klass);
+        CFCSymbol **methods     = (CFCSymbol**)CFCClass_methods(klass);
+        OK(test, S_has_symbol(inert_vars, "num_dogs"), "parsed inert var");
+        OK(test, S_has_symbol(member_vars, "mom"), "parsed public member var");
+        OK(test, S_has_symbol(member_vars, "squishy"),
+           "parsed parcel member var");
+        OK(test, S_has_symbol(functions, "init"), "parsed function");
+        OK(test, S_has_symbol(methods, "chase_tail"), "parsed private method");
+        OK(test, S_has_symbol(methods, "destroy"), "parsed parcel method");
+        OK(test, S_has_symbol(methods, "bury"), "parsed public method");
+        OK(test, S_has_symbol(methods, "scratch"),
+           "parsed public abstract nullable method");
+
+        CFCMethod *scratch = CFCClass_method(klass, "scratch");
+        OK(test, scratch != NULL, "find method 'scratch'");
+        OK(test, CFCType_nullable(CFCMethod_get_return_type(scratch)),
+           "public abstract incremented nullable flagged as nullable");
+
+        int num_public_methods = 0;
+        for (int i = 0; methods[i]; ++i) {
+            if (CFCSymbol_public(methods[i])) { ++num_public_methods; }
+        }
+        INT_EQ(test, num_public_methods, 6, "pass acl to Method constructor");
+
+        OK(test, CFCClass_has_attribute(klass, "lovable"),
+           "parsed class attribute");
+        OK(test, CFCClass_has_attribute(klass, "drooly"),
+           "parsed second class attribute");
+
+        CFCBase_decref((CFCBase*)klass);
+    }
+
+    {
+        const char *class_src =
+            "parcel inert class Rigor::Mortis cnick Mort {\n"
+            "    parcel inert void lie_still();\n"
+            "}\n";
+        CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+        OK(test, CFCClass_inert(klass),
+           "inert modifier parsed and passed to constructor");
+
+        CFCBase_decref((CFCBase*)klass);
+    }
+
+    {
+        const char *class_src =
+            "final class Ultimo {\n"
+            "    /** Throws an error.\n"
+            "     */\n"
+            "    void Say_Never(Ultimo *self);\n"
+            "}\n";
+        CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+        OK(test, CFCClass_final(klass), "final class_declaration");
+        CFCBase_decref((CFCBase*)klass);
+    }
+
+    CFCBase_decref((CFCBase*)parser);
+    CFCBase_decref((CFCBase*)neato);
+    CFCBase_decref((CFCBase*)file_spec);
+    CFCBase_decref((CFCBase*)thing);
+    CFCBase_decref((CFCBase*)widget);
+    CFCBase_decref((CFCBase*)tread_water);
+    CFCBase_decref((CFCBase*)foo);
+    CFCBase_decref((CFCBase*)foo_jr);
+    CFCBase_decref((CFCBase*)final_foo);
+    CFCBase_decref((CFCBase*)do_stuff);
+
+    CFCClass_clear_registry();
+    CFCParcel_reap_singletons();
+}
+
+static int
+S_has_symbol(CFCSymbol **symbols, const char *micro_sym) {
+    for (int i = 0; symbols[i]; ++i) {
+        if (strcmp(CFCSymbol_micro_sym(symbols[i]), micro_sym) == 0) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTestFileSpec.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestFileSpec.c 
b/clownfish/compiler/src/CFCTestFileSpec.c
new file mode 100644
index 0000000..2cddfa8
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestFileSpec.c
@@ -0,0 +1,54 @@
+/* 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 CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCFileSpec.h"
+#include "CFCTest.h"
+
+static void
+S_run_basic_tests(CFCTest *test);
+
+void
+CFCTestFileSpec_run(CFCTest *test) {
+    CFCTest_start_batch(test, "file_spec", 4);
+
+    S_run_basic_tests(test);
+}
+
+static void
+S_run_basic_tests(CFCTest *test) {
+    {
+        CFCFileSpec *file_spec
+            = CFCFileSpec_new("Clownfish/_include", "Stuff/Thing", 0);
+        STR_EQ(test, CFCFileSpec_get_source_dir(file_spec),
+               "Clownfish/_include", "get_source_dir");
+        STR_EQ(test, CFCFileSpec_get_path_part(file_spec),
+               "Stuff/Thing", "get_path_part");
+        OK(test, !CFCFileSpec_included(file_spec), "not included");
+
+        CFCBase_decref((CFCBase*)file_spec);
+    }
+
+    {
+        CFCFileSpec *file_spec
+            = CFCFileSpec_new("Clownfish/_include", "Stuff/Thing", 1);
+        OK(test, CFCFileSpec_included(file_spec), "included");
+
+        CFCBase_decref((CFCBase*)file_spec);
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTestParamList.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestParamList.c 
b/clownfish/compiler/src/CFCTestParamList.c
new file mode 100644
index 0000000..16f0a1e
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestParamList.c
@@ -0,0 +1,78 @@
+/* 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 CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCParamList.h"
+#include "CFCParcel.h"
+#include "CFCParser.h"
+#include "CFCTest.h"
+#include "CFCVariable.h"
+
+static void
+S_run_basic_tests(CFCTest *test);
+
+void
+CFCTestParamList_run(CFCTest *test) {
+    CFCTest_start_batch(test, "param_list", 16);
+
+    S_run_basic_tests(test);
+}
+
+static void
+S_run_basic_tests(CFCTest *test) {
+    CFCParser *parser = CFCParser_new();
+    CFCParcel *neato_parcel
+        = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+
+    {
+        CFCParamList *param_list
+            = CFCTest_parse_param_list(test, parser, "(Obj *self, int num)");
+        OK(test, !CFCParamList_variadic(param_list), "not variadic");
+        STR_EQ(test, CFCParamList_to_c(param_list), "neato_Obj* self, int num",
+               "to_c");
+        STR_EQ(test, CFCParamList_name_list(param_list), "self, num",
+               "name_list");
+
+        CFCBase_decref((CFCBase*)param_list);
+    }
+
+    {
+        CFCParamList *param_list
+            = CFCTest_parse_param_list(test, parser,
+                                       "(Obj *self=NULL, int num, ...)");
+        OK(test, CFCParamList_variadic(param_list), "variadic");
+        STR_EQ(test, CFCParamList_to_c(param_list),
+               "neato_Obj* self, int num, ...", "to_c");
+        INT_EQ(test, CFCParamList_num_vars(param_list), 2, "num_vars");
+        const char **initial_values
+            = CFCParamList_get_initial_values(param_list);
+        STR_EQ(test, initial_values[0], "NULL", "initial_values[0]"); 
+        OK(test, initial_values[1] == NULL, "initial_values[1]");
+        CFCVariable **variables = CFCParamList_get_variables(param_list);
+        OK(test, variables[0] != NULL, "get_variables");
+        STR_EQ(test, CFCBase_get_cfc_class((CFCBase*)variables[0]),
+               "Clownfish::CFC::Model::Variable", "get_variables return type");
+
+        CFCBase_decref((CFCBase*)param_list);
+    }
+
+    CFCBase_decref((CFCBase*)parser);
+    CFCBase_decref((CFCBase*)neato_parcel);
+
+    CFCParcel_reap_singletons();
+}
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/64602a2a/clownfish/compiler/src/CFCTestVariable.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestVariable.c 
b/clownfish/compiler/src/CFCTestVariable.c
new file mode 100644
index 0000000..f6673e0
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestVariable.c
@@ -0,0 +1,101 @@
+/* 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 CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCParcel.h"
+#include "CFCParser.h"
+#include "CFCSymbol.h"
+#include "CFCTest.h"
+#include "CFCType.h"
+#include "CFCVariable.h"
+
+static void
+S_run_basic_tests(CFCTest *test);
+
+void
+CFCTestVariable_run(CFCTest *test) {
+    CFCTest_start_batch(test, "variable", 27);
+
+    S_run_basic_tests(test);
+}
+
+static void
+S_run_basic_tests(CFCTest *test) {
+    CFCParser *parser = CFCParser_new();
+    CFCParcel *neato_parcel
+        = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+
+    {
+        CFCType *type = CFCTest_parse_type(test, parser, "float*");
+        CFCVariable *var
+            = CFCVariable_new(NULL, NULL, NULL, NULL, "foo", type, 0);
+        STR_EQ(test, CFCVariable_local_c(var), "float* foo", "local_c");
+        STR_EQ(test, CFCVariable_local_declaration(var), "float* foo;",
+               "local_declaration");
+        OK(test, CFCSymbol_local((CFCSymbol*)var), "default to local access");
+
+        CFCBase_decref((CFCBase*)type);
+        CFCBase_decref((CFCBase*)var);
+    }
+
+    {
+        CFCType *type = CFCTest_parse_type(test, parser, "float[1]");
+        CFCVariable *var
+            = CFCVariable_new(NULL, NULL, NULL, NULL, "foo", type, 0);
+        STR_EQ(test, CFCVariable_local_c(var), "float foo[1]",
+               "to_c appends array to var name rather than type specifier");
+
+        CFCBase_decref((CFCBase*)type);
+        CFCBase_decref((CFCBase*)var);
+    }
+
+    {
+        CFCType *type = CFCTest_parse_type(test, parser, "Foo*");
+        CFCVariable *var
+            = CFCVariable_new(neato_parcel, NULL,
+                              "Crustacean::Lobster::LobsterClaw", "LobClaw",
+                              "foo", type, 0);
+        STR_EQ(test, CFCVariable_global_c(var), "neato_Foo* neato_LobClaw_foo",
+               "global_c");
+
+        CFCBase_decref((CFCBase*)type);
+        CFCBase_decref((CFCBase*)var);
+    }
+
+    {
+        static const char *variable_strings[7] = {
+            "parcel int foo;",
+            "private Obj *obj;",
+            "public inert int32_t **foo;",
+            "Dog *fido;",
+            "uint32_t baz",
+            "CharBuf *stuff",
+            "float **ptr"
+        };
+        for (int i = 0; i < 7; ++i) {
+            CFCVariable *var
+                = CFCTest_parse_variable(test, parser, variable_strings[i]);
+            CFCBase_decref((CFCBase*)var);
+        }
+    }
+
+    CFCBase_decref((CFCBase*)parser);
+    CFCBase_decref((CFCBase*)neato_parcel);
+
+    CFCParcel_reap_singletons();
+}
+

Reply via email to