1 /**
2 * collectd - src/ceph_test.c
3 * Copyright (C) 2015 Florian octo Forster
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * Authors:
19 * Florian octo Forster <octo at collectd.org>
20 **/
21
22 #include "ceph.c" /* sic */
23 #include "testing.h"
24
25 struct case_s {
26 const char *key;
27 const char *value;
28 };
29 typedef struct case_s case_t;
30
31 struct test_s {
32 case_t *cases;
33 size_t cases_num;
34 };
35 typedef struct test_s test_t;
36
test_handler(void * user,char const * val,char const * key)37 static int test_handler(void *user, char const *val, char const *key) {
38 test_t *t = user;
39 size_t i;
40
41 char status[1024];
42 bool ok;
43
44 /* special case for latency metrics. */
45 if (strcmp("filestore.example_latency", key) == 0)
46 return RETRY_AVGCOUNT;
47
48 snprintf(status, sizeof(status),
49 "unexpected call: test_handler(\"%s\") = \"%s\"", key, val);
50 ok = false;
51
52 for (i = 0; i < t->cases_num; i++) {
53 if (strcmp(key, t->cases[i].key) != 0)
54 continue;
55
56 if (strcmp(val, t->cases[i].value) != 0) {
57 snprintf(status, sizeof(status),
58 "test_handler(\"%s\") = \"%s\", want \"%s\"", key, val,
59 t->cases[i].value);
60 ok = false;
61 break;
62 }
63
64 snprintf(status, sizeof(status), "test_handler(\"%s\") = \"%s\"", key, val);
65 ok = true;
66 break;
67 }
68
69 OK1(ok, status);
70 return ok ? 0 : -1;
71 }
72
DEF_TEST(traverse_json)73 DEF_TEST(traverse_json) {
74 char const *json =
75 "{\n"
76 " \"WBThrottle\": {\n"
77 " \"bytes_dirtied\": {\n"
78 " \"type\": 2,\n"
79 " \"description\": \"Dirty data\",\n"
80 " \"nick\": \"\"\n"
81 " },\n"
82 " \"bytes_wb\": {\n"
83 " \"type\": 2,\n"
84 " \"description\": \"Written data\",\n"
85 " \"nick\": \"\"\n"
86 " },\n"
87 " \"ios_dirtied\": {\n"
88 " \"type\": 2,\n"
89 " \"description\": \"Dirty operations\",\n"
90 " \"nick\": \"\"\n"
91 " },\n"
92 " \"ios_wb\": {\n"
93 " \"type\": 2,\n"
94 " \"description\": \"Written operations\",\n"
95 " \"nick\": \"\"\n"
96 " },\n"
97 " \"inodes_dirtied\": {\n"
98 " \"type\": 2,\n"
99 " \"description\": \"Entries waiting for write\",\n"
100 " \"nick\": \"\"\n"
101 " },\n"
102 " \"inodes_wb\": {\n"
103 " \"type\": 10,\n"
104 " \"description\": \"Written entries\",\n"
105 " \"nick\": \"\"\n"
106 " }\n"
107 " },\n"
108 " \"filestore\": {\n"
109 " \"journal_wr_bytes\": {\n"
110 " \"avgcount\": 23,\n"
111 " \"sum\": 3117\n"
112 " },\n"
113 " \"example_latency\": {\n"
114 " \"avgcount\": 42,\n"
115 " \"sum\": 4711\n"
116 " }\n"
117 " }\n"
118 "}\n";
119 case_t cases[] = {
120 {"WBThrottle.bytes_dirtied.type", "2"},
121 {"WBThrottle.bytes_wb.type", "2"},
122 {"WBThrottle.ios_dirtied.type", "2"},
123 {"WBThrottle.ios_wb.type", "2"},
124 {"WBThrottle.inodes_dirtied.type", "2"},
125 {"WBThrottle.inodes_wb.type", "10"},
126 {"filestore.journal_wr_bytes.sum", "3117"},
127 {"filestore.example_latency.avgcount", "42"},
128 {"filestore.example_latency.sum", "4711"},
129 };
130 test_t t = {cases, STATIC_ARRAY_SIZE(cases)};
131
132 yajl_struct ctx = {test_handler, &t};
133
134 yajl_handle hndl;
135 #if HAVE_YAJL_V2
136 hndl = yajl_alloc(&callbacks, NULL, &ctx);
137 CHECK_ZERO(
138 traverse_json((const unsigned char *)json, (uint32_t)strlen(json), hndl));
139 CHECK_ZERO(yajl_complete_parse(hndl));
140 #else
141 hndl = yajl_alloc(&callbacks, NULL, NULL, &ctx);
142 CHECK_ZERO(
143 traverse_json((const unsigned char *)json, (uint32_t)strlen(json), hndl));
144 CHECK_ZERO(yajl_parse_complete(hndl));
145 #endif
146
147 yajl_free(hndl);
148 return 0;
149 }
150
DEF_TEST(parse_keys)151 DEF_TEST(parse_keys) {
152 struct {
153 const char *str;
154 const char *want;
155 } cases[] = {
156 {"WBThrottle.bytes_dirtied.description.bytes_wb.description.ios_dirtied."
157 "description.ios_wb.type",
158 "WBThrottle.bytesDirtied.description.bytesWb.description.iosDirt"},
159 {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:"
160 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
161 "Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
162 {"foo:bar", "FooBar"},
163 {"foo:bar+", "FooBarPlus"},
164 {"foo:bar-", "FooBarMinus"},
165 {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+",
166 "AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPlus"},
167 {"aa.bb.cc.dd.ee.ff", "Aa.bb.cc.dd.ee.ff"},
168 {"aa.bb.cc.dd.ee.ff.type", "Aa.bb.cc.dd.ee.ff"},
169 {"aa.type", "Aa.type"},
170 {"WBThrottle.bytes_dirtied.type", "WBThrottle.bytesDirtied"},
171 };
172 size_t i;
173
174 for (i = 0; i < STATIC_ARRAY_SIZE(cases); i++) {
175 char got[64];
176
177 CHECK_ZERO(parse_keys(got, sizeof(got), cases[i].str));
178 EXPECT_EQ_STR(cases[i].want, got);
179 }
180
181 return 0;
182 }
183
main(void)184 int main(void) {
185 RUN_TEST(traverse_json);
186 RUN_TEST(parse_keys);
187
188 END_TEST;
189 }
190