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