static void S_run_overridden_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*"); CFCParamList *param_list = CFCTest_parse_param_list(test, parser, "(Foo *self)"); CFCMethod *orig = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Return_An_Obj", return_type, param_list, NULL, 0, 0); CFCParamList *overrider_param_list = CFCTest_parse_param_list(test, parser, "(FooJr *self)"); CFCMethod *overrider = CFCMethod_new(neato_parcel, NULL, "Neato::Foo::FooJr", "FooJr", "Return_An_Obj", return_type, overrider_param_list, NULL, 0, 0); CFCMethod_override(overrider, orig); OK(test, !CFCMethod_novel(overrider), "A Method which overrides another is not 'novel'"); CFCBase_decref((CFCBase*)parser); CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)return_type); CFCBase_decref((CFCBase*)param_list); CFCBase_decref((CFCBase*)orig); CFCBase_decref((CFCBase*)overrider_param_list); CFCBase_decref((CFCBase*)overrider); CFCParcel_reap_singletons(); }
static void S_run_parser_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); CFCParser_set_class_name(parser, "Neato::Obj"); CFCParser_set_class_nickname(parser, "Obj"); { static const char *method_strings[4] = { "public int Do_Foo(Obj *self);", "Obj* Gimme_An_Obj(Obj *self);", "void Do_Whatever(Obj *self, uint32_t a_num, float real);", "Foo* Fetch_Foo(Obj *self, int num);", }; for (int i = 0; i < 4; ++i) { CFCMethod *method = CFCTest_parse_method(test, parser, method_strings[i]); CFCBase_decref((CFCBase*)method); } } { CFCMethod *method = CFCTest_parse_method(test, parser, "public final void The_End(Obj *self);"); OK(test, CFCMethod_final(method), "final"); CFCBase_decref((CFCBase*)method); } CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)parser); CFCParcel_reap_singletons(); }
static void S_run_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*"); CFCParamList *param_list = CFCTest_parse_param_list(test, parser, "(int32_t some_num)"); { CFCFunction *func = CFCFunction_new(NULL, "return_an_obj", return_type, param_list, NULL, 0); OK(test, func != NULL, "new"); CFCBase_decref((CFCBase*)func); } { CFCFunction *func = NULL; char *error; CFCUTIL_TRY { func = CFCFunction_new(NULL, "Uh_Oh", return_type, param_list, NULL, 0); } CFCUTIL_CATCH(error); OK(test, error && strstr(error, "Uh_Oh"), "invalid name kills constructor"); FREEMEM(error); CFCBase_decref((CFCBase*)func); } { CFCClass *neato_obj = CFCClass_create(neato_parcel, NULL, "Neato::Obj", NULL, NULL, NULL, NULL, false, false, false); CFCParser_set_class(parser, neato_obj); static const char *func_strings[2] = { "inert int running_count(int biscuit);", "public inert Hash* init_fave_hash(int32_t num_buckets," " bool o_rly);" }; for (int i = 0; i < 2; ++i) { CFCFunction *func = CFCTest_parse_function(test, parser, func_strings[i]); CFCBase_decref((CFCBase*)func); } CFCBase_decref((CFCBase*)neato_obj); } CFCBase_decref((CFCBase*)return_type); CFCBase_decref((CFCBase*)param_list); CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)parser); CFCParcel_reap_singletons(); }
static void S_run_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); { CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*"); CFCParamList *param_list = CFCTest_parse_param_list(test, parser, "(int32_t some_num)"); CFCFunction *func = CFCFunction_new(neato_parcel, NULL, "Neato::Foo", "Foo", "return_an_obj", return_type, param_list, NULL, 0); OK(test, func != NULL, "new"); CFCBase_decref((CFCBase*)return_type); CFCBase_decref((CFCBase*)param_list); CFCBase_decref((CFCBase*)func); } { CFCParser_set_class_name(parser, "Neato::Obj"); CFCParser_set_class_cnick(parser, "Obj"); static const char *func_strings[2] = { "inert int running_count(int biscuit);", "public inert Hash* init_fave_hash(int32_t num_buckets," " bool o_rly);" }; for (int i = 0; i < 2; ++i) { CFCFunction *func = CFCTest_parse_function(test, parser, func_strings[i]); CFCBase_decref((CFCBase*)func); } } CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)parser); CFCParcel_reap_singletons(); }
static void S_run_final_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); CFCClass *obj_class = CFCTest_parse_class(test, parser, "class Obj {}"); CFCClass *foo_class = CFCTest_parse_class(test, parser, "class Neato::Foo {}"); CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*"); CFCParamList *param_list = CFCTest_parse_param_list(test, parser, "(Foo *self)"); CFCMethod *not_final = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Return_An_Obj", return_type, param_list, NULL, 0, 0); CFCMethod_resolve_types(not_final); CFCMethod *final = CFCMethod_finalize(not_final); OK(test, CFCMethod_compatible(not_final, final), "finalize clones properly"); OK(test, !CFCMethod_final(not_final), "not final by default"); OK(test, CFCMethod_final(final), "finalize"); CFCBase_decref((CFCBase*)parser); CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)obj_class); CFCBase_decref((CFCBase*)foo_class); CFCBase_decref((CFCBase*)return_type); CFCBase_decref((CFCBase*)param_list); CFCBase_decref((CFCBase*)not_final); CFCBase_decref((CFCBase*)final); CFCClass_clear_registry(); CFCParcel_reap_singletons(); }
static void S_run_basic_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*"); CFCParamList *param_list = CFCTest_parse_param_list(test, parser, "(Foo *self, int32_t count = 0)"); CFCMethod *method = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Return_An_Obj", return_type, param_list, NULL, 0, 0); OK(test, method != NULL, "new"); OK(test, CFCSymbol_parcel((CFCSymbol*)method), "parcel exposure by default"); { CFCMethod *dupe = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Return_An_Obj", return_type, param_list, NULL, 0, 0); OK(test, CFCMethod_compatible(method, dupe), "compatible"); CFCBase_decref((CFCBase*)dupe); } { CFCMethod *macro_sym_differs = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Eat", return_type, param_list, NULL, 0, 0); OK(test, !CFCMethod_compatible(method, macro_sym_differs), "different macro_sym spoils compatible"); OK(test, !CFCMethod_compatible(macro_sym_differs, method), "... reversed"); CFCBase_decref((CFCBase*)macro_sym_differs); } { static const char *param_strings[5] = { "(Foo *self, int32_t count = 0, int b)", "(Foo *self, int32_t count = 1)", "(Foo *self, int32_t count)", "(Foo *self, int32_t countess = 0)", "(Foo *self, uint32_t count = 0)" }; static const char *test_names[5] = { "extra param", "different initial_value", "missing initial_value", "different param name", "different param type" }; for (int i = 0; i < 5; ++i) { CFCParamList *other_param_list = CFCTest_parse_param_list(test, parser, param_strings[i]); CFCMethod *other = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Return_An_Obj", return_type, other_param_list, NULL, 0, 0); OK(test, !CFCMethod_compatible(method, other), "%s spoils compatible", test_names[i]); OK(test, !CFCMethod_compatible(other, method), "... reversed"); CFCBase_decref((CFCBase*)other_param_list); CFCBase_decref((CFCBase*)other); } } { CFCParamList *self_differs_list = CFCTest_parse_param_list(test, parser, "(Bar *self, int32_t count = 0)"); CFCMethod *self_differs = CFCMethod_new(neato_parcel, NULL, "Neato::Bar", "Bar", "Return_An_Obj", return_type, self_differs_list, NULL, 0, 0); OK(test, CFCMethod_compatible(method, self_differs), "different self type still compatible()," " since can't test inheritance"); OK(test, CFCMethod_compatible(self_differs, method), "... reversed"); CFCBase_decref((CFCBase*)self_differs_list); CFCBase_decref((CFCBase*)self_differs); } { CFCMethod *aliased = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Aliased", return_type, param_list, NULL, 0, 0); OK(test, !CFCMethod_get_host_alias(aliased), "no host alias by default"); CFCMethod_set_host_alias(aliased, "Host_Alias"); STR_EQ(test, CFCMethod_get_host_alias(aliased), "Host_Alias", "set/get host alias"); CFCBase_decref((CFCBase*)aliased); } { CFCMethod *excluded = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Excluded", return_type, param_list, NULL, 0, 0); OK(test, !CFCMethod_excluded_from_host(excluded), "not excluded by default"); CFCMethod_exclude_from_host(excluded); OK(test, CFCMethod_excluded_from_host(excluded), "exclude from host"); CFCBase_decref((CFCBase*)excluded); } CFCBase_decref((CFCBase*)parser); CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)return_type); CFCBase_decref((CFCBase*)param_list); CFCBase_decref((CFCBase*)method); CFCParcel_reap_singletons(); }
static void S_run_object_tests(CFCTest *test) { static const char *modifiers[4] = { "const", "incremented", "decremented", "nullable" }; static int flags[4] = { CFCTYPE_CONST, CFCTYPE_INCREMENTED, CFCTYPE_DECREMENTED, CFCTYPE_NULLABLE }; static int (*accessors[4])(CFCType *type) = { CFCType_const, CFCType_incremented, CFCType_decremented, CFCType_nullable }; { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); static const char *specifiers[4] = { "Foo", "FooJr", "FooIII", "Foo4th" }; for (int i = 0; i < 4; ++i) { const char *specifier = specifiers[i]; char *class_code = CFCUtil_sprintf("class %s {}", specifier); CFCClass *klass = CFCTest_parse_class(test, parser, class_code); FREEMEM(class_code); static const char *prefixes[2] = { "", "neato_" }; char *expect = CFCUtil_sprintf("neato_%s", specifier); for (int j = 0; j < 2; ++j) { char *src = CFCUtil_sprintf("%s%s*", prefixes[j], specifier); CFCType *type = CFCTest_parse_type(test, parser, src); CFCType_resolve(type); STR_EQ(test, CFCType_get_specifier(type), expect, "object_type_specifier: %s", src); OK(test, CFCType_is_object(type), "%s is_object", src); INT_EQ(test, CFCType_get_indirection(type), 1, "%s indirection", src); FREEMEM(src); CFCBase_decref((CFCBase*)type); } FREEMEM(expect); for (int j = 0; j < 4; ++j) { char *src = CFCUtil_sprintf("%s %s*", modifiers[j], specifier); CFCType *type = CFCTest_parse_type(test, parser, src); OK(test, CFCType_is_object(type), "%s is_object", src); OK(test, accessors[j](type), "%s accessor", src); FREEMEM(src); CFCBase_decref((CFCBase*)type); } CFCBase_decref((CFCBase*)klass); CFCClass_clear_registry(); } CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)parser); } CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL, NULL); CFCClass *foo_class = CFCClass_create(neato_parcel, NULL, "Foo", NULL, NULL, NULL, NULL, NULL, false, false, false); CFCType *foo = CFCType_new_object(0, neato_parcel, "Foo", 1); CFCType_resolve(foo); { CFCType *another_foo = CFCType_new_object(0, neato_parcel, "Foo", 1); CFCType_resolve(another_foo); OK(test, CFCType_equals(foo, another_foo), "equals"); CFCBase_decref((CFCBase*)another_foo); } { CFCClass *bar_class = CFCClass_create(neato_parcel, NULL, "Bar", NULL, NULL, NULL, NULL, NULL, false, false, false); CFCType *bar = CFCType_new_object(0, neato_parcel, "Bar", 1); CFCType_resolve(bar); OK(test, !CFCType_equals(foo, bar), "different specifier spoils equals"); CFCBase_decref((CFCBase*)bar); CFCBase_decref((CFCBase*)bar_class); } { CFCParcel *foreign_parcel = CFCParcel_new("Foreign", NULL, NULL, NULL); CFCClass *foreign_foo_class = CFCClass_create(foreign_parcel, NULL, "Foreign::Foo", NULL, NULL, NULL, NULL, NULL, false, false, false); CFCType *foreign_foo = CFCType_new_object(0, foreign_parcel, "Foo", 1); CFCType_resolve(foreign_foo); OK(test, !CFCType_equals(foo, foreign_foo), "different parcel spoils equals"); STR_EQ(test, CFCType_get_specifier(foreign_foo), "foreign_Foo", "prepend parcel prefix to specifier"); CFCBase_decref((CFCBase*)foreign_parcel); CFCBase_decref((CFCBase*)foreign_foo_class); CFCBase_decref((CFCBase*)foreign_foo); } { for (int i = 0; i < 4; ++i) { CFCType *modified_foo = CFCType_new_object(flags[i], neato_parcel, "Foo", 1); CFCType_resolve(modified_foo); OK(test, accessors[i](modified_foo), "%s", modifiers[i]); OK(test, !accessors[i](foo), "not %s", modifiers[i]); OK(test, !CFCType_equals(foo, modified_foo), "different %s spoils equals", modifiers[i]); OK(test, !CFCType_similar(foo, modified_foo), "different %s spoils similar", modifiers[i]); CFCBase_decref((CFCBase*)modified_foo); } } { CFCType *string_type = CFCType_new_object(0, neato_parcel, "String", 1); OK(test, CFCType_is_string_type(string_type), "%s", "is_string_type"); OK(test, !CFCType_is_string_type(foo), "not %s", "not is_string_type"); CFCBase_decref((CFCBase*)string_type); } CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)foo_class); CFCBase_decref((CFCBase*)foo); CFCClass_clear_registry(); CFCParcel_reap_singletons(); }
static void S_run_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); OK(test, parser != NULL, "new"); { CFCParcel *fish = CFCTest_parse_parcel(test, parser, "parcel Fish;"); CFCParcel *registered = CFCParcel_new("Crustacean", "Crust", NULL, false); CFCParcel_register(registered); CFCParcel *parcel = CFCTest_parse_parcel(test, parser, "parcel Crustacean;"); OK(test, parcel == registered, "Fetch registered parcel"); OK(test, CFCParser_get_parcel(parser) == parcel, "parcel_definition sets internal var"); CFCBase_decref((CFCBase*)fish); CFCBase_decref((CFCBase*)registered); CFCBase_decref((CFCBase*)parcel); } { static const char *const specifiers[8] = { "foo", "_foo", "foo_yoo", "FOO", "Foo", "fOO", "f00", "foo_foo_foo" }; for (int i = 0; i < 8; ++i) { const char *specifier = specifiers[i]; char *src = CFCUtil_sprintf("int32_t %s;", specifier); CFCVariable *var = CFCTest_parse_variable(test, parser, src); STR_EQ(test, CFCVariable_micro_sym(var), specifier, "identifier/declarator: %s", specifier); FREEMEM(src); CFCBase_decref((CFCBase*)var); } } { static const char *const specifiers[6] = { "void", "float", "uint32_t", "int64_t", "uint8_t", "bool" }; for (int i = 0; i < 6; ++i) { const char *specifier = specifiers[i]; char *src = CFCUtil_sprintf("int32_t %s;", specifier); CFCBase *result = CFCParser_parse(parser, src); OK(test, result == NULL, "reserved word not parsed as identifier: %s", specifier); FREEMEM(src); CFCBase_decref(result); } } { static const char *const type_strings[7] = { "bool", "const char *", "Obj*", "i32_t", "char[]", "long[1]", "i64_t[30]" }; for (int i = 0; i < 7; ++i) { const char *type_string = type_strings[i]; CFCType *type = CFCTest_parse_type(test, parser, type_string); CFCBase_decref((CFCBase*)type); } } { static const char *const class_names[7] = { "ByteBuf", "Obj", "ANDMatcher", "Foo", "FooJr", "FooIII", "Foo4th" }; CFCClass *class_list[8]; for (int i = 0; i < 7; ++i) { char *class_code = CFCUtil_sprintf("class %s {}", class_names[i]); CFCClass *klass = CFCTest_parse_class(test, parser, class_code); class_list[i] = klass; FREEMEM(class_code); } class_list[7] = NULL; for (int i = 0; i < 7; ++i) { const char *class_name = class_names[i]; char *src = CFCUtil_sprintf("%s*", class_name); char *expected = CFCUtil_sprintf("crust_%s", class_name); CFCType *type = CFCTest_parse_type(test, parser, src); CFCType_resolve(type, class_list); STR_EQ(test, CFCType_get_specifier(type), expected, "object_type_specifier: %s", class_name); FREEMEM(src); FREEMEM(expected); CFCBase_decref((CFCBase*)type); } for (int i = 0; i < 7; ++i) { CFCBase_decref((CFCBase*)class_list[i]); } CFCClass_clear_registry(); } { CFCType *type = CFCTest_parse_type(test, parser, "const char"); OK(test, CFCType_const(type), "type_qualifier const"); CFCBase_decref((CFCBase*)type); } { static const char *const exposures[2] = { "public", "" }; static int (*const accessors[2])(CFCSymbol *sym) = { CFCSymbol_public, CFCSymbol_parcel }; for (int i = 0; i < 2; ++i) { const char *exposure = exposures[i]; char *src = CFCUtil_sprintf("%s inert int32_t foo;", exposure); CFCVariable *var = CFCTest_parse_variable(test, parser, src); OK(test, accessors[i]((CFCSymbol*)var), "exposure_specifier %s", exposure); FREEMEM(src); CFCBase_decref((CFCBase*)var); } } { static const char *const hex_constants[] = { "0x1", "0x0a", "0xFFFFFFFF", "-0xFC", NULL }; S_test_initial_value(test, parser, hex_constants, "int32_t", "hex_constant:"); } { static const char *const integer_constants[] = { "1", "-9999", "0", "10000", NULL }; S_test_initial_value(test, parser, integer_constants, "int32_t", "integer_constant:"); } { static const char *const float_constants[] = { "1.0", "-9999.999", "0.1", "0.0", NULL }; S_test_initial_value(test, parser, float_constants, "double", "float_constant:"); } { static const char *const string_literals[] = { "\"blah\"", "\"blah blah\"", "\"\\\"blah\\\" \\\"blah\\\"\"", NULL }; S_test_initial_value(test, parser, string_literals, "String*", "string_literal:"); } { static const char *const composites[5] = { "int[]", "i32_t **", "Foo **", "Foo ***", "const void *" }; for (int i = 0; i < 5; ++i) { const char *composite = composites[i]; CFCType *type = CFCTest_parse_type(test, parser, composite); OK(test, CFCType_is_composite(type), "composite_type: %s", composite); CFCBase_decref((CFCBase*)type); } } { static const char *const object_types[5] = { "Obj *", "incremented Foo*", "decremented String *" }; for (int i = 0; i < 3; ++i) { const char *object_type = object_types[i]; CFCType *type = CFCTest_parse_type(test, parser, object_type); OK(test, CFCType_is_object(type), "object_type: %s", object_type); CFCBase_decref((CFCBase*)type); } } { static const char *const param_list_strings[3] = { "()", "(int foo)", "(Obj *foo, Foo **foo_ptr)" }; for (int i = 0; i < 3; ++i) { const char *param_list_string = param_list_strings[i]; CFCParamList *param_list = CFCTest_parse_param_list(test, parser, param_list_string); INT_EQ(test, CFCParamList_num_vars(param_list), i, "param list num_vars: %d", i); CFCBase_decref((CFCBase*)param_list); } } { CFCParamList *param_list = CFCTest_parse_param_list(test, parser, "(int foo, ...)"); OK(test, CFCParamList_variadic(param_list), "variadic param list"); CFCBase_decref((CFCBase*)param_list); } { const char *param_list_string = "(int foo = 0xFF, char *bar =\"blah\")"; CFCParamList *param_list = CFCTest_parse_param_list(test, parser, param_list_string); const char **initial_values = CFCParamList_get_initial_values(param_list); STR_EQ(test, initial_values[0], "0xFF", "param list initial_values[0]"); STR_EQ(test, initial_values[1], "\"blah\"", "param list initial_values[1]"); OK(test, initial_values[2] == NULL, "param list initial_values[2]"); CFCBase_decref((CFCBase*)param_list); } { CFCParser_set_class_name(parser, "Stuff::Obj"); CFCParser_set_class_cnick(parser, "Obj"); const char *method_string = "public Foo* Spew_Foo(Obj *self, uint32_t *how_many);"; CFCMethod *method = CFCTest_parse_method(test, parser, method_string); CFCBase_decref((CFCBase*)method); const char *var_string = "public inert Hash *hash;"; CFCVariable *var = CFCTest_parse_variable(test, parser, var_string); CFCBase_decref((CFCBase*)var); } { static const char *const class_names[4] = { "Foo", "Foo::FooJr", "Foo::FooJr::FooIII", "Foo::FooJr::FooIII::Foo4th" }; for (int i = 0; i < 4; ++i) { const char *class_name = class_names[i]; char *class_string = CFCUtil_sprintf("class %s { }", class_name); CFCClass *klass = CFCTest_parse_class(test, parser, class_string); STR_EQ(test, CFCClass_get_class_name(klass), class_name, "class_name: %s", class_name); FREEMEM(class_string); CFCBase_decref((CFCBase*)klass); } } { static const char *const cnicks[2] = { "Food", "FF" }; for (int i = 0; i < 2; ++i) { const char *cnick = cnicks[i]; char *class_string = CFCUtil_sprintf("class Foodie%s cnick %s { }", cnick, cnick); CFCClass *klass = CFCTest_parse_class(test, parser, class_string); STR_EQ(test, CFCClass_get_cnick(klass), cnick, "cnick: %s", cnick); FREEMEM(class_string); CFCBase_decref((CFCBase*)klass); } } CFCBase_decref((CFCBase*)parser); CFCClass_clear_registry(); CFCParcel_reap_singletons(); }