Exemple #1
0
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();
}
Exemple #2
0
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();
}
Exemple #3
0
static void
S_run_tests(CFCTest *test) {
    CFCParser *parser = CFCParser_new();

    {
        CFCCBlock *block = CFCCBlock_new("int foo;");
        STR_EQ(test, CFCCBlock_get_contents(block), "int foo;",
               "get_contents");
        CFCBase_decref((CFCBase*)block);
    }

    {
        const char *cblock_string =
            " __C__\n"
            "#define FOO_BAR 1\n"
            "__END_C__  ";
        CFCBase *result = CFCParser_parse(parser, cblock_string);
        OK(test, result != NULL, "parse cblock");
        STR_EQ(test, CFCBase_get_cfc_class(result),
               "Clownfish::CFC::Model::CBlock", "result class of cblock");
        CFCCBlock *block = (CFCCBlock*)result;
        STR_EQ(test, CFCCBlock_get_contents(block), "#define FOO_BAR 1\n",
               "parse embed_c");
        CFCBase_decref((CFCBase*)block);
    }

    CFCBase_decref((CFCBase*)parser);
}
static void
S_run_void_tests(CFCTest *test) {
    CFCParser *parser = CFCParser_new();

    {
        CFCType *type = CFCType_new_void(false);
        STR_EQ(test, CFCType_get_specifier(type), "void", "get_specifier");
        STR_EQ(test, CFCType_to_c(type), "void", "to_c");
        OK(test, CFCType_is_void(type), "is_void");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCType *type = CFCType_new_void(true);
        STR_EQ(test, CFCType_to_c(type), "const void",
               "'const' in C representation");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCType *type = CFCTest_parse_type(test, parser, "void");
        OK(test, CFCType_is_void(type), "void is_void");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCType *type = CFCTest_parse_type(test, parser, "const void");
        OK(test, CFCType_is_void(type), "const void is_void");
        OK(test, CFCType_const(type), "const void is const");
        CFCBase_decref((CFCBase*)type);
    }

    CFCBase_decref((CFCBase*)parser);
}
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_integer_tests(CFCTest *test) {
    {
        CFCType *type = CFCType_new_integer(CFCTYPE_CONST, "int32_t");
        OK(test, CFCType_const(type), "const");
        STR_EQ(test, CFCType_get_specifier(type), "int32_t", "get_specifier");
        STR_EQ(test, CFCType_to_c(type), "const int32_t",
               "'const' in C representation");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCParser *parser = CFCParser_new();
        static const char *specifiers[14] = {
            "bool",
            "char",
            "short",
            "int",
            "long",
            "size_t",
            "int8_t",
            "int16_t",
            "int32_t",
            "int64_t",
            "uint8_t",
            "uint16_t",
            "uint32_t",
            "uint64_t"
        };
        for (int i = 0; i < 14; ++i) {
            const char *specifier = specifiers[i];
            CFCType *type;

            type = CFCTest_parse_type(test, parser, specifier);
            OK(test, CFCType_is_integer(type), "%s is_integer", specifier);
            CFCBase_decref((CFCBase*)type);

            char *const_specifier = CFCUtil_sprintf("const %s", specifier);
            type = CFCTest_parse_type(test, parser, const_specifier);
            OK(test, CFCType_is_integer(type), "%s is_integer",
               const_specifier);
            OK(test, CFCType_const(type), "%s is const", const_specifier);
            FREEMEM(const_specifier);
            CFCBase_decref((CFCBase*)type);
        }
        CFCBase_decref((CFCBase*)parser);
    }
}
static void
S_run_va_list_tests(CFCTest *test) {
    {
        CFCType *type = CFCType_new_va_list();
        STR_EQ(test, CFCType_get_specifier(type), "va_list",
               "specifier defaults to 'va_list'");
        STR_EQ(test, CFCType_to_c(type), "va_list", "to_c");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCParser *parser = CFCParser_new();
        CFCType *type = CFCTest_parse_type(test, parser, "va_list");
        OK(test, CFCType_is_va_list(type), "is_va_list");
        CFCBase_decref((CFCBase*)type);
        CFCBase_decref((CFCBase*)parser);
    }
}
Exemple #8
0
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_arbitrary_tests(CFCTest *test) {
    {
        CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL, NULL);
        CFCParcel_register(neato_parcel);

        CFCType *foo = CFCType_new_arbitrary(neato_parcel, "foo_t");
        STR_EQ(test, CFCType_get_specifier(foo), "foo_t", "get_specifier");
        STR_EQ(test, CFCType_to_c(foo), "foo_t", "to_c");

        CFCType *twin = CFCType_new_arbitrary(neato_parcel, "foo_t");
        OK(test, CFCType_equals(foo, twin), "equals");

        CFCType *compare_t
            = CFCType_new_arbitrary(neato_parcel, "Sort_compare_t");
        OK(test, !CFCType_equals(foo, compare_t),
           "equals spoiled by different specifier");

        CFCBase_decref((CFCBase*)neato_parcel);
        CFCBase_decref((CFCBase*)foo);
        CFCBase_decref((CFCBase*)compare_t);
        CFCBase_decref((CFCBase*)twin);
    }

    {
        CFCParser *parser = CFCParser_new();
        static const char *specifiers[2] = { "foo_t", "Sort_compare_t" };
        for (int i = 0; i < 2; ++i) {
            const char *specifier = specifiers[i];
            CFCType *type = CFCTest_parse_type(test, parser, specifier);
            OK(test, CFCType_is_arbitrary(type), "arbitrary type %s",
               specifier);
            CFCBase_decref((CFCBase*)type);
        }
        CFCBase_decref((CFCBase*)parser);
    }

    CFCParcel_reap_singletons();
}
Exemple #10
0
CFCHierarchy*
CFCHierarchy_init(CFCHierarchy *self, const char *dest) {
    if (!dest || !strlen(dest)) {
        CFCUtil_die("'dest' is required");
    }
    self->sources      = (char**)CALLOCATE(1, sizeof(char*));
    self->num_sources  = 0;
    self->includes     = (char**)CALLOCATE(1, sizeof(char*));
    self->num_includes = 0;
    self->prereqs      = (char**)CALLOCATE(1, sizeof(char*));
    self->num_prereqs  = 0;
    self->dest         = CFCUtil_strdup(dest);
    self->trees        = (CFCClass**)CALLOCATE(1, sizeof(CFCClass*));
    self->num_trees    = 0;
    self->files        = (CFCFile**)CALLOCATE(1, sizeof(CFCFile*));
    self->num_files    = 0;
    self->parser       = CFCParser_new();

    self->inc_dest = CFCUtil_sprintf("%s" CHY_DIR_SEP "include", self->dest);
    self->src_dest = CFCUtil_sprintf("%s" CHY_DIR_SEP "source", self->dest);

    return self;
}
static void
S_run_float_tests(CFCTest *test) {
    {
        CFCType *type = CFCType_new_float(CFCTYPE_CONST, "float");
        OK(test, CFCType_const(type), "const");
        STR_EQ(test, CFCType_get_specifier(type), "float", "get_specifier");
        STR_EQ(test, CFCType_to_c(type), "const float",
               "'const' in C representation");
        CFCBase_decref((CFCBase*)type);
    }

    {
        CFCParser *parser = CFCParser_new();
        static const char *specifiers[2] = {
            "float",
            "double"
        };
        for (int i = 0; i < 2; ++i) {
            const char *specifier = specifiers[i];
            CFCType *type;

            type = CFCTest_parse_type(test, parser, specifier);
            OK(test, CFCType_is_floating(type), "%s is_floating", specifier);
            CFCBase_decref((CFCBase*)type);

            char *const_specifier = CFCUtil_sprintf("const %s", specifier);
            type = CFCTest_parse_type(test, parser, const_specifier);
            OK(test, CFCType_is_floating(type), "%s is_floating",
               const_specifier);
            OK(test, CFCType_const(type), "%s is const", const_specifier);
            FREEMEM(const_specifier);
            CFCBase_decref((CFCBase*)type);
        }
        CFCBase_decref((CFCBase*)parser);
    }
}
Exemple #12
0
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_tests(CFCTest *test) {
#define STUFF_THING "Stuff" CHY_DIR_SEP "Thing"

    CFCParser *parser = CFCParser_new();
    CFCFileSpec *file_spec = CFCFileSpec_new(".", STUFF_THING, 0);

    {
        const char *string =
            "parcel Stuff;\n"
            "class Stuff::Thing {\n"
            "    Foo *foo;\n"
            "    Bar *bar;\n"
            "}\n"
            "class Foo {}\n"
            "class Bar {}\n"
            "__C__\n"
            "int foo;\n"
            "__END_C__\n";
        CFCFile *file = CFCParser_parse_file(parser, string, file_spec);

        STR_EQ(test, CFCFile_get_source_dir(file), ".", "get_source_dir");
        STR_EQ(test, CFCFile_get_path_part(file), STUFF_THING,
               "get_path_part");
        OK(test, !CFCFile_included(file), "included");

        STR_EQ(test, CFCFile_guard_name(file), "H_STUFF_THING", "guard_name");
        STR_EQ(test, CFCFile_guard_start(file),
               "#ifndef H_STUFF_THING\n#define H_STUFF_THING 1\n",
               "guard_start");
        STR_EQ(test, CFCFile_guard_close(file), "#endif /* H_STUFF_THING */\n",
               "guard_close");

        OK(test, !CFCFile_get_modified(file), "modified false at start");
        CFCFile_set_modified(file, 1);
        OK(test, CFCFile_get_modified(file), "set_modified, get_modified");

#define PATH_TO_STUFF_THING \
    "path" CHY_DIR_SEP \
    "to" CHY_DIR_SEP \
    "Stuff" CHY_DIR_SEP \
    "Thing"

        char *cfh_path = CFCFile_cfh_path(file, "path/to");
        STR_EQ(test, cfh_path, PATH_TO_STUFF_THING ".cfh", "cfh_path");
        FREEMEM(cfh_path);
        char *c_path = CFCFile_c_path(file, "path/to");
        STR_EQ(test, c_path, PATH_TO_STUFF_THING ".c", "c_path");
        FREEMEM(c_path);
        char *h_path = CFCFile_h_path(file, "path/to");
        STR_EQ(test, h_path, PATH_TO_STUFF_THING ".h", "h_path");
        FREEMEM(h_path);

        CFCClass **classes = CFCFile_classes(file);
        OK(test,
           classes[0] != NULL && classes[1] != NULL && classes[2] != NULL
           && classes[3] == NULL,
           "classes() filters blocks");
        CFCVariable **member_vars = CFCClass_fresh_member_vars(classes[0]);
        CFCType *foo_type = CFCVariable_get_type(member_vars[0]);
        CFCType_resolve(foo_type);
        STR_EQ(test, CFCType_get_specifier(foo_type), "stuff_Foo",
               "file production picked up parcel def");
        CFCType *bar_type = CFCVariable_get_type(member_vars[1]);
        CFCType_resolve(bar_type);
        STR_EQ(test, CFCType_get_specifier(bar_type), "stuff_Bar",
               "parcel def is sticky");

        CFCParcel *parcel = CFCFile_get_parcel(file);
        STR_EQ(test, CFCParcel_get_name(parcel), "Stuff", "get_parcel");

        CFCBase **blocks = CFCFile_blocks(file);
        STR_EQ(test, CFCBase_get_cfc_class(blocks[0]),
               "Clownfish::CFC::Model::Class", "blocks[0]");
        STR_EQ(test, CFCBase_get_cfc_class(blocks[1]),
               "Clownfish::CFC::Model::Class", "blocks[1]");
        STR_EQ(test, CFCBase_get_cfc_class(blocks[2]),
               "Clownfish::CFC::Model::Class", "blocks[2]");
        STR_EQ(test, CFCBase_get_cfc_class(blocks[3]),
               "Clownfish::CFC::Model::CBlock", "blocks[3]");
        OK(test, blocks[4] == NULL, "blocks[4]");

        CFCBase_decref((CFCBase*)file);

        CFCClass_clear_registry();
    }

    CFCBase_decref((CFCBase*)file_spec);
    CFCBase_decref((CFCBase*)parser);

    CFCParcel_reap_singletons();
}
static void
S_run_composite_tests(CFCTest *test) {
    CFCParser *parser = CFCParser_new();
    CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL, NULL);
    CFCParser_set_parcel(parser, neato_parcel);

    {
        static const char *type_strings[14] = {
            "char*",
            "char**",
            "char***",
            "int32_t*",
            "Obj**",
            "int8_t[]",
            "int8_t[1]",
            "neato_method_t[]",
            "neato_method_t[1]",
            "multi_dimensional_t[1][10]",
            "char * * ",
            "const Obj**",
            "const void*",
            "int8_t[ 3 ]"
        };
        for (int i = 0; i < 14; ++i) {
            const char *type_string = type_strings[i];
            CFCType *type = CFCTest_parse_type(test, parser, type_string);
            OK(test, CFCType_is_composite(type), "composite type %s",
               type_string);
            CFCBase_decref((CFCBase*)type);
        }
    }

    {
        CFCType *foo = CFCType_new_object(0, neato_parcel, "Foo", 1);
        CFCType *const_foo
            = CFCType_new_object(CFCTYPE_CONST, neato_parcel, "Foo", 1);

        CFCType *composite = CFCType_new_composite(0, foo, 1, NULL);
        OK(test, CFCType_is_composite(composite), "is_composite");
        STR_EQ(test, CFCType_get_specifier(composite), "Foo",
               "get_specifier delegates to child" );

        CFCType *twin = CFCType_new_composite(0, foo, 1, NULL);
        OK(test, CFCType_equals(composite, twin), "equals");
        CFCBase_decref((CFCBase*)twin);

        CFCType *const_composite
            = CFCType_new_composite(0, const_foo, 1, NULL);
        OK(test, !CFCType_equals(composite, const_composite),
           "equals spoiled by different child");
        CFCBase_decref((CFCBase*)const_composite);

        CFCBase_decref((CFCBase*)composite);
        CFCBase_decref((CFCBase*)foo);
        CFCBase_decref((CFCBase*)const_foo);
    }

    {
        CFCType *foo_array = CFCTest_parse_type(test, parser, "foo_t[]");
        CFCType_resolve(foo_array);
        STR_EQ(test, CFCType_get_array(foo_array), "[]", "get_array");
        STR_EQ(test, CFCType_to_c(foo_array), "foo_t",
               "array subscripts not included by to_c");
        CFCType *foo_array_array
            = CFCTest_parse_type(test, parser, "foo_t[][]");
        OK(test, !CFCType_equals(foo_array, foo_array_array),
           "equals spoiled by different array postfixes");

        CFCBase_decref((CFCBase*)foo_array);
        CFCBase_decref((CFCBase*)foo_array_array);
    }

    {
        CFCType *foo_star = CFCTest_parse_type(test, parser, "foo_t*");
        CFCType *foo_star_star = CFCTest_parse_type(test, parser, "foo_t**");
        OK(test, !CFCType_equals(foo_star, foo_star_star),
           "equals spoiled by different levels of indirection");
        INT_EQ(test, CFCType_get_indirection(foo_star), 1,
               "foo_t* indirection");
        INT_EQ(test, CFCType_get_indirection(foo_star_star), 2,
               "foo_t** indirection");

        CFCBase_decref((CFCBase*)foo_star);
        CFCBase_decref((CFCBase*)foo_star_star);
    }

    CFCBase_decref((CFCBase*)neato_parcel);
    CFCBase_decref((CFCBase*)parser);
}
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();
}
Exemple #16
0
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();
}
Exemple #17
0
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();
}