src/utils_parse_json.c: Implement parse_json().
[collectd.git] / src / utils_parse_json_test.c
diff --git a/src/utils_parse_json_test.c b/src/utils_parse_json_test.c
new file mode 100644 (file)
index 0000000..761e0c0
--- /dev/null
@@ -0,0 +1,190 @@
+/**
+ * collectd - src/tests/utils_parse_json_test.c
+ * Copyright (C) 2018  Florian Forster
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "utils_parse_json.h"
+#include "testing.h"
+
+DEF_TEST(single_value) /* {{{ */
+{
+  char const *json =
+      "["
+      /* gauge */
+      "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
+      /* gauge (NaN) */
+      "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"gauge\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":[\"gauge\"],\"values\":[null]},"
+      /* derive */
+      "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"total_things\","
+      "\"plugin_instance\":\"foo\",\"type_instance\":\"bar\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":[\"derive\"],\"values\":[31337]}"
+      "]";
+
+  value_list_t **vls = NULL;
+  size_t vls_num = 0;
+
+  CHECK_ZERO(parse_json(json, &vls, &vls_num));
+  OK(vls_num == 3);
+  if (vls_num != 3)
+    return (-1);
+
+  value_list_t *vl = vls[0];
+  EXPECT_EQ_STR("example.com", vl->host);
+  EXPECT_EQ_STR("test", vl->plugin);
+  EXPECT_EQ_STR("", vl->plugin_instance);
+  EXPECT_EQ_STR("answer", vl->type);
+  EXPECT_EQ_STR("", vl->type_instance);
+  OK(vl->time == 1540129631229236480);
+  OK(vl->interval == 10737418240);
+  OK(vl->values_len == 1);
+  OK(vl->values[0].gauge == 42.0);
+
+  vl = vls[1];
+  OK(vl->values_len == 1);
+  OK(isnan(vl->values[0].gauge));
+
+  vl = vls[2];
+  EXPECT_EQ_STR("example.com", vl->host);
+  EXPECT_EQ_STR("test", vl->plugin);
+  EXPECT_EQ_STR("foo", vl->plugin_instance);
+  EXPECT_EQ_STR("total_things", vl->type);
+  EXPECT_EQ_STR("bar", vl->type_instance);
+  OK(vl->time == 1540129631229236480);
+  OK(vl->interval == 10737418240);
+  OK(vl->values_len == 1);
+  OK(vl->values[0].derive == 31337);
+
+  free(vls[0]->values);
+  free(vls[0]);
+  free(vls[1]->values);
+  free(vls[1]);
+  free(vls);
+  return (0);
+} /* }}} single_value */
+
+DEF_TEST(multi_value) /* {{{ */
+{
+  char const *json =
+      "["
+      "{\"host\":\"example.com\",\"plugin\":\"load\",\"type\":\"load\","
+      "\"time\":1434357493,\"interval\":10,"
+      "\"dstypes\":[\"gauge\",\"gauge\",\"gauge\"],\"values\":[1.12,0.56,0.64]}"
+      "]";
+
+  value_list_t **vls = NULL;
+  size_t vls_num = 0;
+
+  CHECK_ZERO(parse_json(json, &vls, &vls_num));
+  OK(vls_num == 1);
+
+  value_list_t *vl = vls[0];
+  EXPECT_EQ_STR("example.com", vl->host);
+  EXPECT_EQ_STR("load", vl->plugin);
+  EXPECT_EQ_STR("load", vl->type);
+  OK(vl->time == 1540129630801887232);
+  OK(vl->interval == 10737418240);
+
+  OK(vl->values_len == 3);
+  OK(vl->values[0].gauge == 1.12);
+  OK(vl->values[1].gauge == 0.56);
+  OK(vl->values[2].gauge == 0.64);
+
+  free(vl->values);
+  free(vl);
+  free(vls);
+  return (0);
+} /* }}} multi_value */
+
+DEF_TEST(failures) /* {{{ */
+{
+  char const *json =
+      "["
+      /* host missing */
+      "{\"plugin\":\"test\",\"type\":\"answer\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
+      /* plugin missing */
+      "{\"host\":\"example.com\",\"type\":\"answer\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
+      /* type missing */
+      "{\"host\":\"example.com\",\"plugin\":\"test\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
+      /* time missing */
+      "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
+      "\"interval\":10.000,"
+      "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
+      /* interval missing */
+      "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
+      "\"time\":1434357493.398,"
+      "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
+      /* derive -> floating point mismatch */
+      "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":[\"derive\"],\"values\":[42.0]},"
+      /* len(dstypes) != len(values) */
+      "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":[\"gauge\"],\"values\":[42.0, 23.0]},"
+      /* type mismatch: got boolean, want string */
+      "{\"host\":true,\"plugin\":\"test\",\"type\":\"answer\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
+      /* type mismatch: got boolean, want number */
+      "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
+      "\"time\":true,\"interval\":10.000,"
+      "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
+      /* type mismatch: got string/number, want array/array */
+      "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
+      "\"time\":1434357493.398,\"interval\":10.000,"
+      "\"dstypes\":\"gauge\",\"values\":42.0}"
+      "]";
+
+  value_list_t **vls = NULL;
+  size_t vls_num = 0;
+
+  CHECK_ZERO(parse_json(json, &vls, &vls_num));
+  CHECK_ZERO(vls_num);
+
+  return (0);
+} /* }}} failures */
+
+int main(int argc, char **argv) /* {{{ */
+{
+  RUN_TEST(single_value);
+  RUN_TEST(multi_value);
+  RUN_TEST(failures);
+
+  END_TEST;
+} /* }}} int main */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */