Statistics
| Branch: | Revision:

napa-baselibs / tests / RepoClient / RepoClient.c @ 507372bb

History | View | Annotate | Download (7.5 KB)

1
#include        <stdio.h>
2
#include        <stdlib.h>
3
#include        <string.h>
4

    
5
#include        <confuse.h>
6
#include        <event2/event.h>
7
#include        <event2/buffer.h>
8
#include        <event2/http.h>
9
#include        <event2/http_struct.h>
10

    
11
#include        <napa.h>
12
#include        <napa_log.h>
13
#include        <repoclient.h>
14
#include        <ml.h>
15

    
16
#define        PUBLISH                "Publish"
17
#define LISTNAMES        "ListMeasurementNames"
18
#define GETPEERS        "GetPeers"
19
#define COUNTPEERS        "CountPeers"
20
#define GETMEASUREMENTS "GetMeasurementRecords"
21

    
22
struct event_base *eventbase;
23

    
24
/* Configuration file parsing instructions. see repoclient_test.cfg for an example */
25
cfg_opt_t opts_listMeasurementNames[] = {
26
        CFG_INT("maxresults", 0, CFGF_NONE),
27
        CFG_STR("channel", NULL, CFGF_NONE),
28
        CFG_END()
29
};
30
cfg_opt_t opts_publish[] = {
31
        CFG_STR("originator", "", CFGF_NONE),
32
        CFG_STR("targetA", "?", CFGF_NONE),
33
        CFG_STR("targetB", NULL, CFGF_NONE),
34
        CFG_STR("name", "", CFGF_NONE),
35
        CFG_FLOAT("value", 0.0, CFGF_NONE),
36
        CFG_STR("string_value", NULL, CFGF_NONE),
37
        CFG_STR("timestamp", "now", CFGF_NONE),
38
        CFG_STR("channel", NULL, CFGF_NONE),
39
        CFG_END()
40
};
41
cfg_opt_t opts_constraint[] = {
42
        CFG_STR("name", "", CFGF_NONE),
43
        CFG_STR("string_value", "", CFGF_NONE),
44
        CFG_FLOAT("min", 0.0, CFGF_NONE),
45
        CFG_FLOAT("max", 0.0, CFGF_NONE),
46
        CFG_END()
47
};
48
cfg_opt_t opts_ranking[] = {
49
        CFG_STR("name", "", CFGF_NONE),
50
        CFG_FLOAT("weight", 1.0, CFGF_NONE),
51
        CFG_END()
52
};
53
cfg_opt_t opts_getpeers[] = {
54
        CFG_INT("maxresults", 0, CFGF_NONE),
55
        CFG_SEC("constraint", opts_constraint, CFGF_MULTI),
56
        CFG_SEC("ranking", opts_ranking, CFGF_MULTI),
57
        CFG_STR("channel", NULL, CFGF_NONE),
58
        CFG_END()
59
        
60
};
61
cfg_opt_t opts_getmeasurements[] = {
62
        CFG_INT("maxresults", 0, CFGF_NONE),
63
        CFG_STR("originator", NULL, CFGF_NONE),
64
        CFG_STR("targetA", NULL, CFGF_NONE),
65
        CFG_STR("targetB", NULL, CFGF_NONE),
66
        CFG_STR("name", NULL, CFGF_NONE),
67
        CFG_STR("channel", NULL, CFGF_NONE),
68
        CFG_END()
69
};
70
cfg_opt_t opts_test[] = {
71
        CFG_SEC(LISTNAMES, opts_listMeasurementNames, CFGF_MULTI),
72
        CFG_SEC(PUBLISH, opts_publish, CFGF_MULTI),
73
        CFG_SEC(GETPEERS, opts_getpeers, CFGF_MULTI),
74
        CFG_SEC(GETMEASUREMENTS, opts_getmeasurements, CFGF_MULTI),
75
        CFG_END()
76
};
77
cfg_opt_t opts_repospec[] = {
78
        CFG_STR("server", "192.168.35.203:9832", CFGF_NONE),
79
        CFG_END()
80
};
81
cfg_opt_t repotest_opts[] = {
82
        CFG_SEC("repository", opts_repospec, CFGF_NONE),
83
        CFG_SEC("test", opts_test, CFGF_MULTI),
84
        CFG_END()
85
};
86

    
87
int tests_done = 0;
88
struct timeval parse_timestamp(const char *ts);
89

    
90
/** Helper to print a string list */
91
const char *print_list(char **list, int n, bool should_free) {
92
        static char buffer[4096];
93
        strcpy(buffer, "[ ");
94
        int i;
95
        for (i = 0; i != n; i++) {
96
                if (i) strcat(buffer, ", ");
97
                strcat(buffer, list[i]);
98
                if (should_free) free(list[i]);
99
        }
100
        strcat(buffer, " ]");
101
        if (should_free) free(list);
102
        return buffer;
103
}
104

    
105
void getMeasurements_callback(HANDLE client, HANDLE id, void *cbarg, MeasurementRecord *result, int n) {
106
        tests_done++;
107
        info("GetMeasurements id %p done, size: %d", id, n);
108
        if (!n) return;
109
        int i;
110
        for (i = 0; i != n; i++) {
111
                debug("i: %d, channel %p", i, result[i].channel);
112
                info("Record %d: %s", i+1, measurementrecord2str(result[i]));
113
        }
114
        free(result);
115
}
116

    
117
void listMeasurementNames_callback(HANDLE client, HANDLE id, void *cbarg, char **result, int n) {
118
        tests_done++;
119
        info("ListMeasurementIds id %p done, result: %s", id, print_list(result, n, 1));
120
}
121

    
122
void getPeers_callback(HANDLE client, HANDLE id, void *cbarg, char **result, int n) {
123
        tests_done++;
124
        info("GetPeers id %p done, result: %s", id, print_list(result, n, 1));
125
}
126

    
127
void publish_callback(HANDLE client, HANDLE id, void *cbarg, int result) {
128
        info("Publish done(id:%p), result %d", id, result);
129
        tests_done++;
130
}
131

    
132
int ntests;
133
cfg_t *cfg;
134
HANDLE repoclient;
135
char *configfile;
136

    
137
void do_tests(HANDLE h, void *arg);
138

    
139
int main(int argc, char *argv[]) {
140
        /* Check for usage (arguments) */
141
        if (argc < 2) {
142
                fprintf(stderr, "Usage: %s repotest.cfg\n", argv[0]);
143
                exit(1);
144
        }
145
        /* Initialize libevent and logging */
146
        eventbase = event_base_new();
147
        napaInitLog(LOG_DEBUG, NULL, NULL);
148
        repInit("");
149

    
150
        /* Parse config file and init repoclient with the "repository" cfg section */
151
        configfile = argv[1];
152
        cfg = cfg_init(repotest_opts, CFGF_NONE);
153
        if(cfg_parse(cfg, configfile) == CFG_PARSE_ERROR)
154
                fatal("Unable to parse config file %s", configfile);
155

    
156
        repoclient = repOpen(cfg_getstr(cfg_getsec(cfg, "repository"), "server"),3);
157
        if (repoclient == NULL) fatal("Unable to initialize repoclient");
158

    
159
        ntests = cfg_size(cfg, "test");
160
        if (!ntests) fatal("No tests specified, exiting");
161

    
162
        struct timeval t = { 1, 0 };
163
        napaSchedulePeriodic(&t, 1.0/5.0, do_tests, NULL);
164
        do_tests(NULL, NULL);
165

    
166
        repClose(repoclient);
167

    
168
        cfg_free(cfg);
169
        event_base_free(eventbase);
170
}
171

    
172
void do_tests(HANDLE h, void *arg) {
173
        int i;
174
        for (i = 0; i != ntests; i++) {
175
                cfg_t *test = cfg_getnsec(cfg, "test", i);
176

    
177
                if ((cfg_size(test, PUBLISH) + cfg_size(test,LISTNAMES) + cfg_size(test,GETPEERS) + 
178
                        cfg_size(test,GETMEASUREMENTS)) != 1)
179
                        fatal("A test clause must contain exactly one action in %s", configfile);
180

    
181
                info("Performing test %d/%d", i+1, ntests);
182
                cfg_t *action;
183

    
184
                if ((action = cfg_getsec(test, PUBLISH)) != NULL) {
185
                        char AsocketID[SOCKETID_SIZE] = "Unknown";
186
                        char BsocketID[SOCKETID_SIZE] = "Unknown";
187
                        MeasurementRecord r;
188
                        r.originator = cfg_getstr(action, "originator");
189
                        r.targetA = cfg_getstr(action, "targetA");
190
                        r.targetB = cfg_getstr(action, "targetB");
191
                        r.published_name = cfg_getstr(action, "name");
192
                        r.value = cfg_getfloat(action, "value");
193
                        r.string_value = cfg_getstr(action, "string_value");
194
                        r.channel = cfg_getstr(action, "channel");
195
                        r.timestamp = parse_timestamp(cfg_getstr(action, "timestamp"));
196
                        repPublish(repoclient, publish_callback, NULL, &r);
197
                }
198
                if ((action = cfg_getsec(test, LISTNAMES)) != NULL) {
199
                        repListMeasurementNames(repoclient, listMeasurementNames_callback, NULL, 
200
                                cfg_getint(action, "maxresults"), cfg_getstr(action, "channel"));
201
                        continue;
202
                }
203
                if ((action = cfg_getsec(test, GETMEASUREMENTS)) != NULL) {
204
                        repGetMeasurements(repoclient, getMeasurements_callback, NULL, 
205
                                cfg_getint(action, "maxresults"),
206
                                cfg_getstr(action, "originator"), cfg_getstr(action, "targetA"), 
207
                                cfg_getstr(action, "targetB"), cfg_getstr(action, "name"),
208
                                cfg_getstr(action, "channel"));
209
                        continue;
210
                }
211
                if ((action = cfg_getsec(test, GETPEERS)) != NULL) {
212
                        int ncons = cfg_size(action, "constraint");
213
                        int nranks = cfg_size(action, "ranking");
214
                        Constraint *cons = NULL;
215
                        Ranking *ranks = NULL;
216
                        if (ncons) cons = calloc(ncons, sizeof(Constraint));
217
                        if (nranks) ranks = calloc(nranks, sizeof(Ranking));
218
                        int j;
219
                        for (j = 0; j != ncons; j++) {
220
                                cfg_t *con = cfg_getnsec(action, "constraint", j);
221
                                cons[j].published_name = cfg_getstr(con, "name");
222
                                cons[j].maxValue = cfg_getfloat(con, "max");
223
                                cons[j].minValue = cfg_getfloat(con, "min");
224
                        }
225
                        for (j = 0; j != nranks; j++) {
226
                                cfg_t *con = cfg_getnsec(action, "ranking", j);
227
                                ranks[j].published_name = cfg_getstr(con, "name");
228
                                ranks[j].weight = cfg_getfloat(con, "weight");
229
                        }
230
                        HANDLE h = repGetPeers(repoclient, getPeers_callback, NULL, 
231
                                cfg_getint(action, "maxresults"),
232
                                cons, ncons, ranks, nranks, cfg_getstr(action, "channel"));
233
                        continue;
234
                }
235
        }
236
        
237
        int last_done = tests_done - 1;
238
        while (tests_done != ntests) {
239
                if (last_done != tests_done) debug("Test %d/%d done", tests_done, ntests);
240
                last_done = tests_done;
241
                event_base_loop(eventbase, EVLOOP_ONCE);
242
        }
243
}
244

    
245
struct timeval parse_timestamp(const char *ts) {
246
        struct timeval ret;
247
        ret.tv_usec = 0;
248
        
249
        if (!strcmp(ts, "now")) {
250
                ret.tv_sec = time(NULL);
251
                return ret;
252
        }
253
        ret.tv_sec = 0;
254
        return ret;
255
}