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(); +} +
