Fix the linking of various tests against GMock
[folly.git] / folly / test / JsonTest.cpp
index 805cb3004ffa56a4855f20a38fb181658ffbe4bd..0145fecbbcd77a6249fc3e875c625c5303fb0b06 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -154,14 +154,14 @@ TEST(Json, BoolConversion) {
 }
 
 TEST(Json, JavascriptSafe) {
-  auto badDouble = (1ll << 63ll) + 1;
+  auto badDouble = int64_t((1ULL << 63ULL) + 1);
   dynamic badDyn = badDouble;
   EXPECT_EQ(folly::toJson(badDouble), folly::to<std::string>(badDouble));
   folly::json::serialization_opts opts;
   opts.javascript_safe = true;
   EXPECT_ANY_THROW(folly::json::serialize(badDouble, opts));
 
-  auto okDouble = 1ll << 63ll;
+  auto okDouble = int64_t(1ULL << 63ULL);
   dynamic okDyn = okDouble;
   EXPECT_EQ(folly::toJson(okDouble), folly::to<std::string>(okDouble));
 }
@@ -190,6 +190,53 @@ TEST(Json, JsonEscape) {
     R"("\b\f\n\r\u0001\t\\\"/\u000b\u0007")");
 }
 
+TEST(Json, EscapeCornerCases) {
+  // The escaping logic uses some bitwise operations to determine
+  // which bytes need escaping 8 bytes at a time. Test that this logic
+  // is correct regardless of positions by planting 2 characters that
+  // may need escaping at each possible position and checking the
+  // result, for varying string lengths.
+
+  folly::json::serialization_opts opts;
+  opts.validate_utf8 = true;
+
+  std::string s;
+  std::string expected;
+  for (bool ascii : {true, false}) {
+    opts.encode_non_ascii = ascii;
+
+    for (size_t len = 2; len < 32; ++len) {
+      for (size_t i = 0; i < len; ++i) {
+        for (size_t j = 0; j < len; ++j) {
+          if (i == j) {
+            continue;
+          }
+
+          s.clear();
+          expected.clear();
+
+          expected.push_back('"');
+          for (size_t pos = 0; pos < len; ++pos) {
+            if (pos == i) {
+              s.push_back('\\');
+              expected.append("\\\\");
+            } else if (pos == j) {
+              s.append("\xe2\x82\xac");
+              expected.append(ascii ? "\\u20ac" : "\xe2\x82\xac");
+            } else {
+              s.push_back('x');
+              expected.push_back('x');
+            }
+          }
+          expected.push_back('"');
+
+          EXPECT_EQ(folly::json::serialize(s, opts), expected) << ascii;
+        }
+      }
+    }
+  }
+}
+
 TEST(Json, JsonNonAsciiEncoding) {
   folly::json::serialization_opts opts;
   opts.encode_non_ascii = true;
@@ -438,10 +485,17 @@ TEST(Json, ParseNumbersAsStrings) {
 }
 
 TEST(Json, SortKeys) {
-  folly::json::serialization_opts opts_on, opts_off;
+  folly::json::serialization_opts opts_on, opts_off, opts_custom_sort;
   opts_on.sort_keys = true;
   opts_off.sort_keys = false;
 
+  opts_custom_sort.sort_keys = false; // should not be required
+  opts_custom_sort.sort_keys_by = [](
+      folly::dynamic const& a, folly::dynamic const& b) {
+    // just an inverse sort
+    return b < a;
+  };
+
   dynamic value = dynamic::object
     ("foo", "bar")
     ("junk", 12)
@@ -462,10 +516,18 @@ TEST(Json, SortKeys) {
     R"({"a":[{"a":"b","c":"d"},12.5,"Yo Dawg",["heh"],null],)"
     R"("another":32.2,"foo":"bar","junk":12})";
 
+  std::string inverse_sorted_keys =
+      R"({"junk":12,"foo":"bar","another":32.2,)"
+      R"("a":[{"c":"d","a":"b"},12.5,"Yo Dawg",["heh"],null]})";
+
   EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_on)));
   EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_off)));
+  EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_custom_sort)));
 
   EXPECT_EQ(sorted_keys, folly::json::serialize(value, opts_on));
+  EXPECT_NE(sorted_keys, folly::json::serialize(value, opts_off));
+  EXPECT_EQ(
+      inverse_sorted_keys, folly::json::serialize(value, opts_custom_sort));
 }
 
 TEST(Json, PrintTo) {