testEqualityDouble.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #include "testBase.h"
  2. #define DoubleList \
  3. /* 零值测试 */ \
  4. X(0.0) \
  5. X(-0.0) \
  6. /* 正负整数边界 */ \
  7. X(1.0) \
  8. X(-1.0) \
  9. X(2.0) \
  10. X(-2.0) \
  11. X(10.0) \
  12. X(-10.0) \
  13. X(100.0) \
  14. X(1000.0) \
  15. X(10000.0) \
  16. X(100000.0) \
  17. /* 简单小数(二进制精确表示) */ \
  18. X(0.5) \
  19. X(-0.5) \
  20. X(0.25) \
  21. X(-0.25) \
  22. X(0.125) \
  23. X(0.0625) \
  24. X(0.03125) \
  25. X(0.015625) \
  26. /* 常见小数 */ \
  27. X(16.89) \
  28. X(-16.89) \
  29. X(123.456) \
  30. X(-123.456) \
  31. X(99.99) \
  32. X(-99.99) \
  33. X(1.5) \
  34. X(2.5) \
  35. X(3.5) \
  36. /* 小于1的小数 */ \
  37. X(0.001) \
  38. X(-0.001) \
  39. X(0.0001) \
  40. X(0.00001) \
  41. X(0.000001) \
  42. X(0.123456789) \
  43. X(0.987654321) \
  44. X(0.111111111111111) \
  45. /* 大数测试 */ \
  46. X(999999.999999) \
  47. X(-999999.999999) \
  48. X(12345678.9) \
  49. X(99999999.0) \
  50. X(123456789.123456) \
  51. X(9876543210.12345) \
  52. /* 科学计数法 - 大数 */ \
  53. X(1.5e10) \
  54. X(-1.5e10) \
  55. X(1.23e8) \
  56. X(9.99e12) \
  57. X(1.0e15) \
  58. X(1.0e18) \
  59. X(1.0e20) \
  60. X(5.55e15) \
  61. /* 科学计数法 - 小数 */ \
  62. X(1.5e-10) \
  63. X(-1.5e-10) \
  64. X(9.87e-5) \
  65. X(1.0e-15) \
  66. X(5.5e-8) \
  67. X(1.0e-18) \
  68. X(1.0e-20) \
  69. X(1.23e-3) \
  70. X(-9.87e-7) \
  71. /* 数学常量 */ \
  72. X(3.14159265358979) \
  73. X(2.71828182845904) \
  74. X(1.41421356237309) \
  75. X(1.73205080756888) \
  76. X(1.61803398874989) \
  77. X(0.69314718055994) \
  78. /* 浮点精度经典测试 */ \
  79. X(0.1) \
  80. X(0.2) \
  81. X(0.3) \
  82. X(0.6) \
  83. X(0.7) \
  84. X(0.9) \
  85. X(0.123456) \
  86. /* 整数边界值 */ \
  87. X(2147483647.0) \
  88. X(-2147483648.0) \
  89. X(4294967295.0) \
  90. X(9007199254740991.0) \
  91. X(-9007199254740991.0) \
  92. /* 极端小值 */ \
  93. X(1.0e-100) \
  94. X(-1.0e-100) \
  95. X(1.0e-200) \
  96. X(1.0e-300) \
  97. X(2.225073858507201e-308) \
  98. /* 极端大值 */ \
  99. X(1.0e100) \
  100. X(-1.0e100) \
  101. X(1.0e200) \
  102. X(1.0e300) \
  103. X(1.797693134862315e308) \
  104. /* 特殊精度值 */ \
  105. X(1.0000000000001) \
  106. X(0.9999999999999) \
  107. X(1.23456789012345) \
  108. X(9.87654321098765) \
  109. /* 重复数字模式 */ \
  110. X(1.1111111111111) \
  111. X(2.2222222222222) \
  112. X(9.9999999999999) \
  113. /* 混合符号和指数 */ \
  114. X(-1.23e-45) \
  115. X(-9.87e67) \
  116. X(1.11e-11) \
  117. X(-2.22e22)
  118. static const double DoubleValueTable[] = {
  119. #define X(a) a,
  120. DoubleList
  121. #undef X
  122. };
  123. static const char *DoubleStringTable[] = {
  124. #define X(a) "{\"double\":" #a "}",
  125. DoubleList
  126. #undef X
  127. };
  128. static const char *DoubleStringTable2[] = {
  129. #define X(a) #a,
  130. DoubleList
  131. #undef X
  132. };
  133. static const char *DoubleStringTable3[] = {
  134. #define X(a) "[" #a "]",
  135. DoubleList
  136. #undef X
  137. };
  138. static RyanJsonBool_e shouldSkipLargeDoubleWhenNoScientific(double value)
  139. {
  140. #if false == RyanJsonSnprintfSupportScientific
  141. /* 不支持科学计数法的平台上,跳过超大值序列化往返校验。 */
  142. return RyanJsonMakeBool(fabs(value) >= 1.0e100);
  143. #else
  144. (void)value;
  145. return RyanJsonFalse;
  146. #endif
  147. }
  148. /**
  149. * @brief 浮点类型边界与一致性测试
  150. */
  151. void testEqualityDoubleEdgeCases(void)
  152. {
  153. // NULL 输入
  154. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsDouble(NULL), "RyanJsonIsDouble(NULL) 应返回 false");
  155. // 类型混淆测试
  156. RyanJson_t num = RyanJsonCreateInt("num", 123);
  157. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsNumber(num), "RyanJsonIsNumber(Int) 应返回 true");
  158. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsDouble(num), "RyanJsonIsDouble(Int) 应返回 false");
  159. RyanJsonDelete(num);
  160. RyanJson_t str = RyanJsonCreateString("str", "123.456");
  161. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsDouble(str), "RyanJsonIsDouble(String) 应返回 false");
  162. RyanJsonDelete(str);
  163. RyanJson_t obj = RyanJsonCreateObject();
  164. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsDouble(obj), "RyanJsonIsDouble(Object) 应返回 false");
  165. RyanJsonDelete(obj);
  166. RyanJson_t boolNode = RyanJsonCreateBool("bool", RyanJsonTrue);
  167. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsDouble(boolNode), "RyanJsonIsDouble(Bool) 应返回 false");
  168. RyanJsonDelete(boolNode);
  169. }
  170. static void testEqualityDoubleTypeIdentity(void)
  171. {
  172. // 指数形式即使数值是整数,也应保持 double 类型
  173. RyanJson_t expNode = RyanJsonParse("1e0");
  174. TEST_ASSERT_NOT_NULL(expNode);
  175. TEST_ASSERT_TRUE(RyanJsonIsDouble(expNode));
  176. TEST_ASSERT_TRUE(RyanJsonCompareDouble(1.0, RyanJsonGetDoubleValue(expNode)));
  177. char *expPrinted = RyanJsonPrint(expNode, 64, RyanJsonFalse, NULL);
  178. TEST_ASSERT_NOT_NULL(expPrinted);
  179. RyanJson_t expRoundtrip = RyanJsonParse(expPrinted);
  180. RyanJsonFree(expPrinted);
  181. TEST_ASSERT_NOT_NULL(expRoundtrip);
  182. TEST_ASSERT_TRUE(RyanJsonIsDouble(expRoundtrip));
  183. TEST_ASSERT_TRUE(RyanJsonCompareDouble(1.0, RyanJsonGetDoubleValue(expRoundtrip)));
  184. RyanJsonDelete(expRoundtrip);
  185. RyanJsonDelete(expNode);
  186. // 小数形式应保持 double
  187. RyanJson_t fracNode = RyanJsonParse("-2.5000");
  188. TEST_ASSERT_NOT_NULL(fracNode);
  189. TEST_ASSERT_TRUE(RyanJsonIsDouble(fracNode));
  190. TEST_ASSERT_TRUE(RyanJsonCompareDouble(-2.5, RyanJsonGetDoubleValue(fracNode)));
  191. RyanJsonDelete(fracNode);
  192. // 超出 int32_t 范围的纯数字,应归类为 double
  193. RyanJson_t overInt = RyanJsonParse("2147483648");
  194. TEST_ASSERT_NOT_NULL(overInt);
  195. TEST_ASSERT_TRUE(RyanJsonIsDouble(overInt));
  196. TEST_ASSERT_FALSE(RyanJsonIsInt(overInt));
  197. TEST_ASSERT_TRUE(RyanJsonCompareDouble(2147483648.0, RyanJsonGetDoubleValue(overInt)));
  198. RyanJsonDelete(overInt);
  199. RyanJson_t belowInt = RyanJsonParse("-2147483649");
  200. TEST_ASSERT_NOT_NULL(belowInt);
  201. TEST_ASSERT_TRUE(RyanJsonIsDouble(belowInt));
  202. TEST_ASSERT_FALSE(RyanJsonIsInt(belowInt));
  203. TEST_ASSERT_TRUE(RyanJsonCompareDouble(-2147483649.0, RyanJsonGetDoubleValue(belowInt)));
  204. RyanJsonDelete(belowInt);
  205. }
  206. static void testEqualityDoubleTableCommon(const char *const *stringTable, RyanJsonBool_e withKey)
  207. {
  208. for (uint32_t i = 0; i < sizeof(DoubleValueTable) / sizeof(DoubleValueTable[0]); i++)
  209. {
  210. double expectValue = DoubleValueTable[i];
  211. if (shouldSkipLargeDoubleWhenNoScientific(expectValue)) { continue; }
  212. const char *jsondoubleStr = stringTable[i];
  213. RyanJson_t jsonRoot = RyanJsonParse(jsondoubleStr);
  214. TEST_ASSERT_NOT_NULL_MESSAGE(jsonRoot, jsondoubleStr);
  215. RyanJson_t valueNode = withKey ? RyanJsonGetObjectToKey(jsonRoot, "double") : jsonRoot;
  216. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDouble(valueNode), withKey ? "字段 'double' 类型错误" : "Root node not double");
  217. // 验证解析后的数值是否正确
  218. double doubleValue = RyanJsonGetDoubleValue(valueNode);
  219. if (!RyanJsonCompareDouble(expectValue, doubleValue))
  220. {
  221. TEST_PRINTF("字符串: %s, 期望: %g, 实际: %g", jsondoubleStr, expectValue, doubleValue);
  222. TEST_FAIL();
  223. }
  224. // 往返校验:序列化后再次解析,数值应保持一致
  225. char *serializedStr = RyanJsonPrint(jsonRoot, 128, RyanJsonFalse, NULL);
  226. if (NULL == serializedStr)
  227. {
  228. TEST_PRINTF("序列化失败样本: %s", jsondoubleStr);
  229. RyanJsonDelete(jsonRoot);
  230. TEST_FAIL_MESSAGE("序列化失败");
  231. }
  232. RyanJsonDelete(jsonRoot);
  233. RyanJson_t roundtripJson = RyanJsonParse(serializedStr);
  234. RyanJsonFree(serializedStr);
  235. if (NULL == roundtripJson)
  236. {
  237. TEST_PRINTF("往返解析失败样本: %s", jsondoubleStr);
  238. TEST_FAIL_MESSAGE("往返测试:重新解析失败");
  239. }
  240. RyanJson_t roundtripValueNode = withKey ? RyanJsonGetObjectToKey(roundtripJson, "double") : roundtripJson;
  241. if (RyanJsonFalse == RyanJsonIsDouble(roundtripValueNode))
  242. {
  243. RyanJsonDelete(roundtripJson);
  244. TEST_FAIL_MESSAGE(withKey ? "往返测试:字段 'double' 类型错误" : "往返测试:Root node not double");
  245. }
  246. double roundtripValue = RyanJsonGetDoubleValue(roundtripValueNode);
  247. if (!RyanJsonCompareDouble(expectValue, roundtripValue))
  248. {
  249. TEST_PRINTF("往返测试失败:期望: %g, 实际: %g", expectValue, roundtripValue);
  250. TEST_FAIL();
  251. }
  252. RyanJsonDelete(roundtripJson);
  253. }
  254. }
  255. static void testEqualityDoubleTable(void)
  256. {
  257. testEqualityDoubleTableCommon(DoubleStringTable, RyanJsonTrue);
  258. }
  259. static void testEqualityDoubleTable2(void)
  260. {
  261. testEqualityDoubleTableCommon(DoubleStringTable2, RyanJsonFalse);
  262. }
  263. static void testEqualityDoubleTable3(void)
  264. {
  265. for (uint32_t i = 0; i < sizeof(DoubleValueTable) / sizeof(DoubleValueTable[0]); i++)
  266. {
  267. double expectValue = DoubleValueTable[i];
  268. if (shouldSkipLargeDoubleWhenNoScientific(expectValue)) { continue; }
  269. const char *jsondoubleStr = DoubleStringTable3[i];
  270. RyanJson_t jsonRoot = RyanJsonParse(jsondoubleStr);
  271. TEST_ASSERT_NOT_NULL_MESSAGE(jsonRoot, jsondoubleStr);
  272. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsArray(jsonRoot), "Root node not array");
  273. TEST_ASSERT_EQUAL_INT_MESSAGE(1, RyanJsonGetSize(jsonRoot), "Array size not 1");
  274. RyanJson_t valueNode = RyanJsonGetObjectByIndex(jsonRoot, 0);
  275. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDouble(valueNode), "Array[0] not double");
  276. double doubleValue = RyanJsonGetDoubleValue(valueNode);
  277. if (!RyanJsonCompareDouble(expectValue, doubleValue))
  278. {
  279. TEST_PRINTF("字符串: %s, 期望: %g, 实际: %g", jsondoubleStr, expectValue, doubleValue);
  280. TEST_FAIL();
  281. }
  282. // 往返校验:序列化后再次解析,数值应保持一致
  283. char *serializedStr = RyanJsonPrint(jsonRoot, 128, RyanJsonFalse, NULL);
  284. if (NULL == serializedStr)
  285. {
  286. TEST_PRINTF("序列化失败样本: %s", jsondoubleStr);
  287. RyanJsonDelete(jsonRoot);
  288. TEST_FAIL_MESSAGE("序列化失败");
  289. }
  290. RyanJsonDelete(jsonRoot);
  291. RyanJson_t roundtripJson = RyanJsonParse(serializedStr);
  292. RyanJsonFree(serializedStr);
  293. if (NULL == roundtripJson)
  294. {
  295. TEST_PRINTF("往返解析失败样本: %s", jsondoubleStr);
  296. TEST_FAIL_MESSAGE("往返测试:重新解析失败");
  297. }
  298. if (RyanJsonFalse == RyanJsonIsArray(roundtripJson))
  299. {
  300. RyanJsonDelete(roundtripJson);
  301. TEST_FAIL_MESSAGE("往返测试:Root node not array");
  302. }
  303. if (1 != RyanJsonGetSize(roundtripJson))
  304. {
  305. RyanJsonDelete(roundtripJson);
  306. TEST_FAIL_MESSAGE("往返测试:Array size not 1");
  307. }
  308. RyanJson_t roundtripValueNode = RyanJsonGetObjectByIndex(roundtripJson, 0);
  309. if (RyanJsonFalse == RyanJsonIsDouble(roundtripValueNode))
  310. {
  311. RyanJsonDelete(roundtripJson);
  312. TEST_FAIL_MESSAGE("往返测试:Array[0] not double");
  313. }
  314. double roundtripValue = RyanJsonGetDoubleValue(roundtripValueNode);
  315. if (!RyanJsonCompareDouble(expectValue, roundtripValue))
  316. {
  317. TEST_PRINTF("往返测试失败:期望: %g, 实际: %g", expectValue, roundtripValue);
  318. TEST_FAIL();
  319. }
  320. RyanJsonDelete(roundtripJson);
  321. }
  322. }
  323. void testEqualityDoubleRunner(void)
  324. {
  325. UnitySetTestFile(__FILE__);
  326. RUN_TEST(testEqualityDoubleEdgeCases);
  327. RUN_TEST(testEqualityDoubleTypeIdentity);
  328. RUN_TEST(testEqualityDoubleTable);
  329. RUN_TEST(testEqualityDoubleTable2);
  330. RUN_TEST(testEqualityDoubleTable3);
  331. }