jsarg_helpers.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #include <cxxreact/JsArgumentHelpers.h>
  8. #include <folly/dynamic.h>
  9. #include <gtest/gtest.h>
  10. #include <algorithm>
  11. using namespace std;
  12. using namespace folly;
  13. using namespace facebook::xplat;
  14. #define EXPECT_JSAE(statement, exstr) \
  15. do { \
  16. try { \
  17. statement; \
  18. FAIL() << "Expected JsArgumentException(" << (exstr) << ") not thrown"; \
  19. } catch (const JsArgumentException &ex) { \
  20. EXPECT_EQ(ex.what(), std::string(exstr)); \
  21. } \
  22. } while (0) // let any other exception escape, gtest will deal.
  23. TEST(JsArgumentHelpersTest, args) {
  24. const bool aBool = true;
  25. const int64_t anInt = 17;
  26. const double aDouble = 3.14;
  27. const string aString = "word";
  28. const dynamic anArray = dynamic::array("a", "b", "c");
  29. const dynamic anObject = dynamic::object("k1", "v1")("k2", "v2");
  30. const string aNumericString = to<string>(anInt);
  31. folly::dynamic args = dynamic::array(
  32. aBool, anInt, aDouble, aString, anArray, anObject, aNumericString);
  33. EXPECT_EQ(jsArgAsBool(args, 0), aBool);
  34. EXPECT_EQ(jsArgAsInt(args, 1), anInt);
  35. EXPECT_EQ(jsArgAsDouble(args, 2), aDouble);
  36. EXPECT_EQ(jsArgAsString(args, 3), aString);
  37. EXPECT_EQ(jsArgAsArray(args, 4), anArray);
  38. EXPECT_EQ(jsArgAsObject(args, 5), anObject);
  39. // const args
  40. const folly::dynamic &cargs = args;
  41. const folly::dynamic &a4 = jsArgAsArray(cargs, 4);
  42. EXPECT_EQ(a4, anArray);
  43. EXPECT_EQ(jsArgAsObject(cargs, 5), anObject);
  44. // helpers returning dynamic should return same object without copying
  45. EXPECT_EQ(&jsArgAsArray(args, 4), &(args[4]));
  46. EXPECT_EQ(&jsArgAsArray(cargs, 4), &(args[4]));
  47. // dynamics returned for mutable args should be mutable. The test is that
  48. // this compiles.
  49. jsArgAsArray(args, 4)[2] = "d";
  50. jsArgAsArray(args, 4)[2] = "c";
  51. // These fail to compile due to constness.
  52. // jsArgAsArray(cargs, 4)[2] = "d";
  53. // jsArgAsArray(cargs, 4)[2] = "c";
  54. // ref-qualified member function tests
  55. EXPECT_EQ(jsArgN(args, 3, &folly::dynamic::getString), aString);
  56. EXPECT_EQ(jsArg(args[3], &folly::dynamic::getString), aString);
  57. // conversions
  58. EXPECT_EQ(jsArgAsDouble(args, 1), anInt * 1.0);
  59. EXPECT_EQ(jsArgAsString(args, 1), aNumericString);
  60. EXPECT_EQ(jsArgAsInt(args, 6), anInt);
  61. // Test exception messages.
  62. // out_of_range
  63. EXPECT_JSAE(
  64. jsArgAsBool(args, 7),
  65. "JavaScript provided 7 arguments for C++ method which references at least "
  66. "8 arguments: out of range in dynamic array");
  67. // Conv range_error (invalid value conversion)
  68. const std::string exhead = "Could not convert argument 3 to required type: ";
  69. const std::string extail = ": Invalid leading character: \"word\"";
  70. try {
  71. jsArgAsInt(args, 3);
  72. FAIL() << "Expected JsArgumentException(" << exhead << "..." << extail
  73. << ") not thrown";
  74. } catch (const JsArgumentException &ex) {
  75. const std::string exwhat = ex.what();
  76. EXPECT_GT(exwhat.size(), exhead.size());
  77. EXPECT_GT(exwhat.size(), extail.size());
  78. EXPECT_TRUE(std::equal(exhead.cbegin(), exhead.cend(), exwhat.cbegin()))
  79. << "JsArgumentException('" << exwhat << "') does not begin with '"
  80. << exhead << "'";
  81. EXPECT_TRUE(std::equal(extail.crbegin(), extail.crend(), exwhat.crbegin()))
  82. << "JsArgumentException('" << exwhat << "') does not end with '"
  83. << extail << "'";
  84. }
  85. // inconvertible types
  86. EXPECT_JSAE(
  87. jsArgAsArray(args, 2),
  88. "Argument 3 of type double is not required type Array");
  89. EXPECT_JSAE(
  90. jsArgAsInt(args, 4),
  91. "Error converting javascript arg 4 to C++: "
  92. "TypeError: expected dynamic type `int/double/bool/string', but had type `array'");
  93. // type predicate failure
  94. EXPECT_JSAE(
  95. jsArgAsObject(args, 4),
  96. "Argument 5 of type array is not required type Object");
  97. }