aboutsummaryrefslogtreecommitdiff
path: root/flatcc/test/reflection_test/reflection_test.c
blob: eef0bd17f99a0b6b974af097e67dc1a22e6fda3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include "flatcc/support/readfile.h"
#include "flatcc/reflection/reflection_reader.h"
#include "flatcc/portable/pcrt.h"

/* -DFLATCC_PORTABLE may help if inttypes.h is missing. */
#ifndef PRId64
#include <inttypes.h>
#endif


/* This is not an exhaustive test. */
int test_schema(const char *monster_bfbs)
{
    void *buffer;
    size_t size;
    int ret = -1;
    reflection_Schema_table_t S;
    reflection_Object_vec_t Objs;
    reflection_Object_table_t Obj;
    reflection_Field_vec_t Flds;
    reflection_Field_table_t F;
    reflection_Type_table_t T;
    size_t k, monster_index;
    reflection_Service_vec_t Svcs;
    reflection_Service_table_t Svc;
    reflection_RPCCall_vec_t Calls;
    reflection_RPCCall_table_t Call;
    size_t call_index;
    const char *strval;

    buffer = readfile(monster_bfbs, 100000, &size);
    if (!buffer) {
        printf("failed to load binary schema\n");
        goto done;
    }
    S = reflection_Schema_as_root(buffer);
    Objs = reflection_Schema_objects(S);
    for (k = 0; k < reflection_Object_vec_len(Objs); ++k) {
        printf("dbg: obj #%d : %s\n", (int)k,
                reflection_Object_name(reflection_Object_vec_at(Objs, k)));
    }
    k = reflection_Object_vec_find(Objs, "MyGame.Example.Monster");
    if (k == flatbuffers_not_found) {
        printf("Could not find monster in schema\n");
        goto done;
    }
    monster_index = k;
    Obj = reflection_Object_vec_at(Objs, k);
    if (strcmp(reflection_Object_name(Obj), "MyGame.Example.Monster")) {
        printf("Found wrong object in schema\n");
        goto done;
    }
    Flds = reflection_Object_fields(Obj);
    k = reflection_Field_vec_find(Flds, "mana");
    if (k == flatbuffers_not_found) {
        printf("Did not find mana field in Monster schema\n");
        goto done;
    }
    F = reflection_Field_vec_at(Flds, k);
    if (reflection_Field_default_integer(F) != 150) {
        printf("mana field has wrong default value\n");
        printf("field name: %s\n", reflection_Field_name(F));
        printf("%"PRId64"\n", (int64_t)reflection_Field_default_integer(F));
        goto done;
    }
    T = reflection_Field_type(F);
    if (reflection_Type_base_type(T) != reflection_BaseType_Short) {
        printf("mana field has wrong type\n");
        goto done;
    }
    if (reflection_Field_optional(F)) {
        printf("mana field is not optional\n");
        goto done;
    }
    k = reflection_Field_vec_find(Flds, "enemy");
    if (k == flatbuffers_not_found) {
        printf("enemy field not found\n");
        goto done;
    }
    T = reflection_Field_type(reflection_Field_vec_at(Flds, k));
    if (reflection_Type_base_type(T) != reflection_BaseType_Obj) {
        printf("enemy is not an object\n");
        goto done;
    }
    if (reflection_Type_index(T) != (int32_t)monster_index) {
        printf("enemy is not a monster\n");
        goto done;
    }
    k = reflection_Field_vec_find(Flds, "testarrayoftables");
    if (k == flatbuffers_not_found) {
        printf("array of tables not found\n");
        goto done;
    }
    T = reflection_Field_type(reflection_Field_vec_at(Flds, k));
    if (reflection_Type_base_type(T) != reflection_BaseType_Vector) {
        printf("array of tables is not of vector type\n");
        goto done;
    }
    if (reflection_Type_element(T) != reflection_BaseType_Obj) {
        printf("array of tables is not a vector of table type\n");
        goto done;
    }
    if (reflection_Type_index(T) != (int32_t)monster_index) {
        printf("array of tables is not a monster vector\n");
        goto done;
    }
    /* list services and calls */
    Svcs = reflection_Schema_services(S);
    for (k = 0; k < reflection_Service_vec_len(Svcs); ++k) {
        Svc = reflection_Service_vec_at(Svcs, k);
        printf("dbg: svc #%d : %s\n", (int)k,
                reflection_Service_name(Svc));
        Calls = reflection_Service_calls(Svc);
        for (call_index = 0 ;
             call_index < reflection_RPCCall_vec_len(Calls) ;
             call_index++) {
            Call = reflection_RPCCall_vec_at(Calls, call_index);
            printf("dbg:    call %d : %s\n", (int)call_index,
                reflection_RPCCall_name(Call));
        }
    }
    /* Within service MyGame.Example.MonsterStorage ... */
    k = reflection_Service_vec_find(Svcs, "MyGame.Example.MonsterStorage");
    if (k == flatbuffers_not_found) {
        printf("Could not find MonsterStorage service in schema\n");
        goto done;
    }
    Svc = reflection_Service_vec_at(Svcs, k);
    /* ... search the RPC call Store */
    Calls = reflection_Service_calls(Svc);
    k = reflection_RPCCall_vec_find(Calls, "Store");
    if (k == flatbuffers_not_found) {
        printf("Could not find call Store in service\n");
        goto done;
    }
    Call = reflection_RPCCall_vec_at(Calls, k);
    /* Ensure request type is MyGame.Example.Monster */
    Obj = reflection_Object_vec_at(Objs, monster_index);
    if (Obj != reflection_RPCCall_request(Call)) {
        printf("Wrong request type of rpc call\n");
        goto done;
    }
    /* Ensure response type is MyGame.Example.Stat */
    k = reflection_Object_vec_find(Objs, "MyGame.Example.Stat");
    if (k == flatbuffers_not_found) {
        printf("Could not find Stat in schema\n");
        goto done;
    }
    Obj = reflection_Object_vec_at(Objs, k);
    if (Obj != reflection_RPCCall_response(Call)) {
        printf("Wrong response type of rpc call\n");
        goto done;
    }
    /* check the call has an attribute "streaming" */
    k = reflection_KeyValue_vec_scan(reflection_RPCCall_attributes(Call), "streaming");
    if (k == flatbuffers_not_found) {
        printf("Could not find attribute in call\n");
        goto done;
    }
    /* check the attribute value is "none" */
    strval = reflection_KeyValue_value(
                reflection_KeyValue_vec_at(reflection_RPCCall_attributes(Call), k));
    if (!strval || 0 != strcmp("none", strval)) {
        printf("Wrong attribute value in call\n");
        goto done;
    }
    ret = 0;
done:
    if (buffer) {
        free(buffer);
    }
    return ret;
}

/* We take arguments so test can run without copying sources. */
#define usage \
"wrong number of arguments:\n" \
"usage: <program> [<output-filename>]\n"

const char *filename = "generated/monster_test.bfbs";

int main(int argc, char *argv[])
{
    /* Avoid assert dialogs on Windows. */
    init_headless_crt();

    if (argc != 1 && argc != 2) {
        fprintf(stderr, usage);
        exit(1);
    }
    if (argc == 2) {
        filename = argv[1];
    }

    return test_schema(filename);
}