/* * Copyright 2022-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "test-mongocrypt.h" #include "mc-check-conversions-private.h" #include "mc-range-encoding-private.h" #include // DBL_MAX #include // INFINITY, NAN #include typedef struct { mc_getTypeInfo32_args_t args; mc_OSTType_Int32 expect; const char *expectError; } Int32Test; static void _test_RangeTest_Encode_Int32(_mongocrypt_tester_t *tester) { Int32Test tests[] = { /* Test cases copied from server Int32_NoBounds test ... begin */ {.args = {.value = INT32_C(2147483647)}, .expect = {.value = UINT32_C(4294967295), .min = 0, .max = UINT32_MAX}}, {.args = {.value = 1}, .expect = {.value = UINT32_C(2147483649), .min = 0, .max = UINT32_MAX}}, {.args = {.value = 0}, .expect = {.value = UINT32_C(2147483648), .min = 0, .max = UINT32_MAX}}, {.args = {.value = -1}, .expect = {.value = UINT32_C(2147483647), .min = 0, .max = UINT32_MAX}}, {.args = {.value = -2}, .expect = {.value = UINT32_C(2147483646), .min = 0, .max = UINT32_MAX}}, {.args = {.value = INT32_C(-2147483647)}, .expect = {.value = 1, .min = 0, .max = UINT32_MAX}}, {.args = {.value = INT32_MIN}, .expect = {.value = 0, .min = 0, .max = UINT32_MAX}}, /* Test cases copied from server Int32_NoBounds test ... end */ /* Test cases copied from server Int32_Bounds test .. begin */ {.args = {.value = 1, .min = OPT_I32(1), .max = OPT_I32(3)}, .expect = {.value = 0, 0, .max = 2}}, {.args = {.value = 0, .min = OPT_I32(0), .max = OPT_I32(1)}, .expect = {.value = 0, .min = 0, .max = 1}}, {.args = {.value = -1, .min = OPT_I32(-1), .max = OPT_I32(0)}, .expect = {.value = 0, .min = 0, .max = 1}}, {.args = {.value = -2, .min = OPT_I32(-2), .max = OPT_I32(0)}, .expect = {.value = 0, .min = 0, .max = 2}}, {.args = {.value = INT32_C(-2147483647), .min = OPT_I32(INT32_MIN), .max = OPT_I32(1)}, .expect = {.value = 1, .min = 0, .max = UINT32_C(2147483649)}}, {.args = {.value = INT32_MIN, .min = OPT_I32(INT32_MIN), .max = OPT_I32(0)}, .expect = {.value = 0, .min = 0, .max = UINT32_C(2147483648)}}, {.args = {.value = 0, .min = OPT_I32(INT32_MIN), .max = OPT_I32(1)}, .expect = {.value = UINT32_C(2147483648), .min = 0, .max = UINT32_C(2147483649)}}, {.args = {.value = 1, .min = OPT_I32(INT32_MIN), .max = OPT_I32(2)}, .expect = {.value = UINT32_C(2147483649), .min = 0, .max = UINT32_C(2147483650)}}, {.args = {.value = INT32_C(2147483647), .min = OPT_I32(-2147483647), .max = OPT_I32(2147483647)}, .expect = {.value = UINT32_C(4294967294), .min = 0, .max = UINT32_C(4294967294)}}, {.args = {.value = INT32_C(2147483647), .min = OPT_I32(INT32_MIN), .max = OPT_I32(2147483647)}, .expect = {.value = UINT32_C(4294967295), .min = 0, .max = UINT32_C(4294967295)}}, {.args = {.value = 15, .min = OPT_I32(10), .max = OPT_I32(26)}, .expect = {.value = 5, .min = 0, .max = 16}}, {.args = {.value = 15, .min = OPT_I32(-10), .max = OPT_I32(55)}, .expect = {.value = 25, .min = 0, .max = 65}}, /* Test cases copied from server Int32_Bounds test ... end */ /* Test cases copied from server Int32_Errors test ... begin */ {.args = {.value = 1, .max = OPT_I32(2)}, .expectError = "Must specify both a lower and upper bound or no bounds."}, {.args = {.value = 1, .min = OPT_I32(0)}, .expectError = "Must specify both a lower and upper bound or no bounds."}, {.args = {.value = 1, .min = OPT_I32(2), .max = OPT_I32(1)}, .expectError = "The minimum value must be less than the maximum value"}, {.args = {.value = 1, .min = OPT_I32(2), .max = OPT_I32(3)}, .expectError = "Value must be greater than or equal to the minimum " "value and less than or equal to the maximum value"}, {.args = {.value = 4, .min = OPT_I32(2), .max = OPT_I32(3)}, .expectError = "Value must be greater than or equal to the minimum " "value and less than or equal to the maximum value"}, {.args = {.value = 4, .min = OPT_I32(INT32_MIN), .max = OPT_I32(INT32_MIN)}, .expectError = "The minimum value must be less than the maximum value"}, /* Test cases copied from server Int32_Errors test ... end */ }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { Int32Test *test = tests + i; mongocrypt_status_t *const status = mongocrypt_status_new(); // Print a description of the test case. printf("_test_RangeTest_Encode_Int32: value=%" PRId32, test->args.value); if (test->args.min.set) { printf(" min=%" PRId32, test->args.min.value); } if (test->args.max.set) { printf(" max=%" PRId32, test->args.max.value); } printf("\n"); mc_OSTType_Int32 got; const bool ok = mc_getTypeInfo32(test->args, &got, status); if (test->expectError) { ASSERT_OR_PRINT_MSG(!ok, "expected error, but got none"); ASSERT_STATUS_CONTAINS(status, test->expectError); } else { ASSERT_OK_STATUS(ok, status); ASSERT_CMPUINT32(got.value, ==, test->expect.value); ASSERT_CMPUINT32(got.min, ==, test->expect.min); ASSERT_CMPUINT32(got.max, ==, test->expect.max); } mongocrypt_status_destroy(status); } } typedef struct { mc_getTypeInfo64_args_t args; mc_OSTType_Int64 expect; const char *expectError; } Int64Test; static void _test_RangeTest_Encode_Int64(_mongocrypt_tester_t *tester) { Int64Test tests[] = { /* Test cases copied from server Int64_NoBounds test ... begin */ {.args = {.value = INT64_C(9223372036854775807)}, .expect = {.value = UINT64_C(18446744073709551615), .min = 0, .max = UINT64_MAX}}, {.args = {.value = 1}, .expect = {.value = UINT64_C(9223372036854775809), .min = 0, .max = UINT64_MAX}}, {.args = {.value = 0}, .expect = {.value = UINT64_C(9223372036854775808), .min = 0, .max = UINT64_MAX}}, {.args = {.value = -1}, .expect = {.value = UINT64_C(9223372036854775807), .min = 0, .max = UINT64_MAX}}, {.args = {.value = -2}, .expect = {.value = UINT64_C(9223372036854775806), .min = 0, .max = UINT64_MAX}}, {.args = {.value = INT64_C(-9223372036854775807)}, .expect = {.value = 1, .min = 0, .max = UINT64_MAX}}, {.args = {.value = INT64_MIN}, .expect = {.value = 0, .min = 0, .max = UINT64_MAX}}, /* Test cases copied from server Int64_NoBounds test ... end */ /* Test cases copied from server Int64_Bounds test ... begin */ {.args = {.value = 1, .min = OPT_I64(1), .max = OPT_I64(2)}, .expect = {.value = 0, .min = 0, .max = 1}}, {.args = {.value = 0, .min = OPT_I64(0), .max = OPT_I64(1)}, .expect = {.value = 0, .min = 0, .max = 1}}, {.args = {.value = -1, .min = OPT_I64(-1), .max = OPT_I64(0)}, .expect = {.value = 0, .min = 0, .max = 1}}, {.args = {.value = -2, .min = OPT_I64(-2), .max = OPT_I64(0)}, .expect = {.value = 0, .min = 0, .max = 2}}, {.args = {.value = INT64_C(-9223372036854775807), .min = OPT_I64(INT64_MIN), .max = OPT_I64(1)}, .expect = {.value = 1, .min = 0, .max = UINT64_C(9223372036854775809)}}, {.args = {.value = INT64_MIN, .min = OPT_I64(INT64_MIN), .max = OPT_I64(0)}, .expect = {.value = 0, .min = 0, .max = UINT64_C(9223372036854775808)}}, {.args = {.value = 0, .min = OPT_I64(INT64_MIN), .max = OPT_I64(37)}, .expect = {.value = UINT64_C(9223372036854775808), .min = 0, .max = UINT64_C(9223372036854775845)}}, {.args = {.value = 1, .min = OPT_I64(INT64_MIN), .max = OPT_I64(42)}, .expect = {.value = UINT64_C(9223372036854775809), .min = 0, .max = UINT64_C(9223372036854775850)}}, {.args = {.value = INT64_C(9223372036854775807), .min = OPT_I64(-9223372036854775807), .max = OPT_I64(9223372036854775807)}, .expect = {.value = UINT64_C(18446744073709551614), .min = 0, .max = UINT64_C(18446744073709551614)}}, {.args = {.value = INT64_C(9223372036854775807), .min = OPT_I64(INT64_MIN), .max = OPT_I64(9223372036854775807)}, .expect = {.value = UINT64_C(18446744073709551615), .min = 0, .max = UINT64_C(18446744073709551615)}}, {.args = {.value = 15, .min = OPT_I64(10), .max = OPT_I64(26)}, .expect = {.value = 5, .min = 0, .max = 16}}, {.args = {.value = 15, .min = OPT_I64(-10), .max = OPT_I64(55)}, .expect = {.value = 25, .min = 0, .max = 65}}, /* Test cases copied from server Int64_Bounds test ... end */ /* Test cases copied from server Int64_Errors test ... begin */ {.args = {.value = 1, .max = OPT_I64(2)}, .expectError = "Must specify both a lower and upper bound or no bounds."}, {.args = {.value = 1, .min = OPT_I64(0)}, .expectError = "Must specify both a lower and upper bound or no bounds."}, {.args = {.value = 1, .min = OPT_I64(2), .max = OPT_I64(1)}, .expectError = "The minimum value must be less than the maximum value"}, {.args = {.value = 1, .min = OPT_I64(2), .max = OPT_I64(3)}, .expectError = "Value must be greater than or equal to the minimum " "value and less than or equal to the maximum value"}, {.args = {.value = 4, .min = OPT_I64(2), .max = OPT_I64(3)}, .expectError = "Value must be greater than or equal to the minimum " "value and less than or equal to the maximum value"}, {.args = {.value = 4, .min = OPT_I64(INT64_MIN), .max = OPT_I64(INT64_MIN)}, .expectError = "The minimum value must be less than the maximum value"}, /* Test cases copied from server Int64_Errors test ... end */ }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { Int64Test *test = tests + i; mongocrypt_status_t *const status = mongocrypt_status_new(); // Print a description of the test case. printf("_test_RangeTest_Encode_Int64: value=%" PRId64, test->args.value); if (test->args.min.set) { printf(" min=%" PRId64, test->args.min.value); } if (test->args.max.set) { printf(" max=%" PRId64, test->args.max.value); } printf("\n"); mc_OSTType_Int64 got; const bool ok = mc_getTypeInfo64(test->args, &got, status); if (test->expectError) { ASSERT_OR_PRINT_MSG(!ok, "expected error, but got none"); ASSERT_STATUS_CONTAINS(status, test->expectError); } else { ASSERT_OK_STATUS(ok, status); ASSERT_CMPUINT64(got.value, ==, test->expect.value); ASSERT_CMPUINT64(got.min, ==, test->expect.min); ASSERT_CMPUINT64(got.max, ==, test->expect.max); } mongocrypt_status_destroy(status); } } #define INT_64_MAX_DOUBLE (double)18446744073709551615ull static void _test_canUsePrecisionModeDouble(_mongocrypt_tester_t *tester) { #define CAN_USE_PRECISION_MODE(lb, ub, prc, expected, expected_bits_out) \ { \ uint32_t bits_out = 0; \ mongocrypt_status_t *const status = mongocrypt_status_new(); \ printf("_test_canUsePrecisionModeDecimal, min: %f, max: %f, prc: %" PRIu32, lb, ub, prc); \ bool result = mc_canUsePrecisionModeDouble(lb, ub, prc, &bits_out, status); \ ASSERT_OK_STATUS(mongocrypt_status_ok(status), status); \ ASSERT(result == expected); \ ASSERT_CMPINT32(expected_bits_out, ==, bits_out); \ mongocrypt_status_destroy(status); \ } #define CAN_USE_PRECISION_MODE_ERRORS(lb, ub, prc, error) \ { \ mongocrypt_status_t *const status = mongocrypt_status_new(); \ printf("_test_canUsePrecisionModeDecimal errors, min: %f, max: %f, prc: %" PRIu32, lb, ub, prc); \ uint32_t bits_out = 0; \ bool result = mc_canUsePrecisionModeDouble(lb, ub, prc, &bits_out, status); \ ASSERT_OR_PRINT_MSG(!result, "expected error, but got none"); \ ASSERT_STATUS_CONTAINS(status, error); \ mongocrypt_status_destroy(status); \ } CAN_USE_PRECISION_MODE(1.0, 16.0, 0, true, 4); CAN_USE_PRECISION_MODE(0.0, 16.0, 0, true, 5); // 2^53 + 1 is where double starts to lose precision, so we need to ensure that we get the // correct value for max_bits out. CAN_USE_PRECISION_MODE_ERRORS(1.0, 9007199254740992.0, 0, "Invalid upper bound for double precision. Absolute"); CAN_USE_PRECISION_MODE_ERRORS(0.0, 9007199254740992.0, 0, "Invalid upper bound for double precision. Absolute"); CAN_USE_PRECISION_MODE(2.718281, 314.159265, 6, true, 29); CAN_USE_PRECISION_MODE_ERRORS(-1000000000.0, 9223372036844775424.0, 0, "Invalid upper bound for double precision. Absolute"); CAN_USE_PRECISION_MODE_ERRORS(2.710000, 314.150000, 2, "Invalid upper bound for double precision. Fractional digits"); CAN_USE_PRECISION_MODE_ERRORS(314.150000, 350.0, 2, "Invalid lower bound for double precision. Fractional digits"); CAN_USE_PRECISION_MODE_ERRORS((double)9007199254740992, INT_64_MAX_DOUBLE, 0, "Invalid upper bound for double precision. Absolute scaled value"); CAN_USE_PRECISION_MODE_ERRORS(-1 * INT_64_MAX_DOUBLE, 1.0, 0, "Invalid lower bound for double precision. Absolute scaled value"); CAN_USE_PRECISION_MODE_ERRORS(-92233720368547.0, 92233720368547.0, 5, "Invalid upper bound for double precision. Absolute"); #undef CAN_USE_PRECISION_MODE #undef CAN_USE_PRECISION_MODE_ERRORS } typedef struct { double value; mc_optional_double_t min; mc_optional_double_t max; mc_optional_int32_t precision; uint64_t expect; mc_optional_uint64_t expectMax; const char *expectError; bool use_range_v1; // By default, use range v2. } DoubleTest; // Smallest and Largest integer that fits in a double before precision is lost #define DOUBLE_MIN_SAFE_INT -9007199254740992 // -2^53 #define DOUBLE_MAX_SAFE_INT 9007199254740992 // 2^53 static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { DoubleTest tests[] = {/* Test cases copied from server Double_Bounds test ... begin */ // Larger numbers map to larger uint64 {.value = -1111, .expect = UINT64_C(4570770991734587392)}, {.value = -111, .expect = UINT64_C(4585860689314185216)}, {.value = -11, .expect = UINT64_C(4600989969312382976)}, {.value = -10, .expect = UINT64_C(4601552919265804288)}, {.value = -3, .expect = UINT64_C(4609434218613702656)}, {.value = -2, .expect = UINT64_C(4611686018427387904)}, {.value = -1, .expect = UINT64_C(4616189618054758400)}, {.value = 1, .expect = UINT64_C(13830554455654793216)}, {.value = 22, .expect = UINT64_C(13850257704024539136)}, {.value = 333, .expect = UINT64_C(13867937850999177216)}, // Larger exponents map to larger uint64 {.value = 33E56, .expect = UINT64_C(14690973652625833878)}, {.value = 22E57, .expect = UINT64_C(14703137697061005818)}, {.value = 11E58, .expect = UINT64_C(14713688953586463292)}, // Smaller exponents map to smaller uint64 {.value = 1E-6, .expect = UINT64_C(13740701229962882445)}, {.value = 1E-7, .expect = UINT64_C(13725520251343122248)}, {.value = 1E-8, .expect = UINT64_C(13710498295186492474)}, {.value = 1E-56, .expect = UINT64_C(12992711961033031890)}, {.value = 1E-57, .expect = UINT64_C(12977434315086142017)}, {.value = 1E-58, .expect = UINT64_C(12962510038552207822)}, // Smaller negative exponents map to smaller uint64 {.value = -1E-06, .expect = UINT64_C(4706042843746669171)}, {.value = -1E-07, .expect = UINT64_C(4721223822366429368)}, {.value = -1E-08, .expect = UINT64_C(4736245778523059142)}, {.value = -1E-56, .expect = UINT64_C(5454032112676519726)}, {.value = -1E-57, .expect = UINT64_C(5469309758623409599)}, {.value = -1E-58, .expect = UINT64_C(5484234035157343794)}, // Larger exponents map to larger uint64 {.value = -33E+56, .expect = UINT64_C(3755770421083717738)}, {.value = -22E+57, .expect = UINT64_C(3743606376648545798)}, {.value = -11E+58, .expect = UINT64_C(3733055120123088324)}, {.value = 0, .expect = UINT64_C(9223372036854775808)}, {.value = -0.0, .expect = UINT64_C(9223372036854775808)}, /* Test cases copied from server Double_Bounds test ... end */ /* Test cases copied from server Double_Errors test ... begin */ {.value = INFINITY, .expectError = "Infinity and NaN double values are not supported."}, {.value = NAN, .expectError = "Infinity and NaN double values are not supported."}, /* Test cases copied from server Double_Errors test ... end */ /* Test cases copied from Double_Bounds_Precision ... begin */ {.value = 3.141592653589, .precision = OPT_I32_C(1), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = UINT64_C(1000031), .expectMax = OPT_U64_C(2097151)}, {.value = 3.141592653589, .precision = OPT_I32_C(2), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 10000314, .expectMax = OPT_U64_C(33554431)}, {.value = 3.141592653589, .precision = OPT_I32_C(3), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 100003141, .expectMax = OPT_U64_C(268435455)}, {.value = 3.141592653589, .precision = OPT_I32_C(4), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 1000031415, .expectMax = OPT_U64_C(2147483647)}, {.value = 3.141592653589, .precision = OPT_I32_C(5), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 10000314159, .expectMax = OPT_U64_C(34359738367)}, {.value = 3.141592653589, .precision = OPT_I32_C(6), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 100003141592, .expectMax = OPT_U64_C(274877906943)}, {.value = 3.141592653589, .precision = OPT_I32_C(7), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 1000031415926, .expectMax = OPT_U64_C(2199023255551)}, {.value = 0, .max = OPT_DOUBLE_C(1), .min = OPT_DOUBLE_C(-1), .precision = OPT_I32_C(3), .expect = 1000, .expectMax = OPT_U64_C(4095)}, {.value = 0, .max = OPT_DOUBLE_C(1), .min = OPT_DOUBLE_C(-1E5), .precision = OPT_I32_C(3), .expect = 100000000, .expectMax = OPT_U64_C(134217727)}, {.value = -1E-33, .max = OPT_DOUBLE_C(1), .min = OPT_DOUBLE_C(-1E5), .precision = OPT_I32_C(3), .expect = 100000000, .expectMax = OPT_U64_C(134217727)}, {.value = 0, .max = OPT_DOUBLE_C(DBL_MAX), .min = OPT_DOUBLE_C(-DBL_MAX), .precision = OPT_I32_C(3), // Applying min/max/precision result in a domain needing >= 64 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 0, .max = OPT_DOUBLE_C(DBL_MAX), .min = OPT_DOUBLE_C(-DBL_MAX), .precision = OPT_I32_C(3), // Applying min/max/precision result in a domain needing >= 64 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), .precision = OPT_I32_C(0), .expect = 3, .expectMax = OPT_U64_C(7)}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), .precision = OPT_I32_C(1), .expect = 31, .expectMax = OPT_U64_C(63)}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), .precision = OPT_I32_C(2), .expect = 314, .expectMax = OPT_U64_C(1023)}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), .precision = OPT_I32_C(3), .expect = 3141, .expectMax = OPT_U64_C(8191)}, {.value = 3.141592653589, .max = OPT_DOUBLE_C(5), .min = OPT_DOUBLE_C(0), .precision = OPT_I32_C(16), .expectError = "Invalid upper bound for double precision"}, {.value = -5, .max = OPT_DOUBLE_C(-1), .min = OPT_DOUBLE_C(-10), .precision = OPT_I32_C(3), .expect = 5000, .expectMax = OPT_U64_C(16383)}, {.value = 1E100, .max = OPT_DOUBLE_C(DBL_MAX), .min = OPT_DOUBLE_C(-DBL_MAX), .precision = OPT_I32_C(3), // Applying min/max/precision result in a domain needing >= 64 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 1E100, .max = OPT_DOUBLE_C(DBL_MAX), .min = OPT_DOUBLE_C(-DBL_MAX), .precision = OPT_I32_C(3), // Applying min/max/precision result in a domain needing >= 64 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 1E9, .max = OPT_DOUBLE_C(1E10), .min = OPT_DOUBLE_C(0), .precision = OPT_I32_C(3), .expect = 1000000000000, .expectMax = OPT_U64_C(17592186044415)}, {.value = 1E9, .max = OPT_DOUBLE_C(1E10), .min = OPT_DOUBLE_C(0), .precision = OPT_I32_C(0), .expect = 1000000000, .expectMax = OPT_U64_C(17179869183)}, {.value = -5, .max = OPT_DOUBLE_C(10), .min = OPT_DOUBLE_C(-10), .precision = OPT_I32_C(0), .expect = 5, .expectMax = OPT_U64_C(31)}, {.value = -5, .max = OPT_DOUBLE_C(10), .min = OPT_DOUBLE_C(-10), .precision = OPT_I32_C(2), .expect = 500, .expectMax = OPT_U64_C(4095)}, {.value = 1E-30, .max = OPT_DOUBLE_C(10E-30), .min = OPT_DOUBLE_C(1E-30), .precision = OPT_I32_C(35), // Applying min/max/precision result in a domain needing >= 53 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, {.value = 1E-30, .max = OPT_DOUBLE_C(10E-30), .min = OPT_DOUBLE_C(1E-30), .precision = OPT_I32_C(35), // Applying min/max/precision result in a domain needing >= 53 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision."}, /* Test max and min integer bounds for doubles */ {.value = DOUBLE_MIN_SAFE_INT, .max = OPT_DOUBLE_C(DOUBLE_MAX_SAFE_INT), .min = OPT_DOUBLE_C(DOUBLE_MIN_SAFE_INT), .precision = OPT_I32_C(0), .expect = 0, // Applying min/max/precision result in a domain needing >= 53 bits to represent. // For range v2, expect an error. .expectError = "Invalid upper bound for double precision. Absolute"}, {.value = 900719925474099.6, .max = OPT_DOUBLE_C(900719925474100.0), .min = OPT_DOUBLE_C(900719925474099.0), .precision = OPT_I32_C(0), .expect = 0, .expectMax = OPT_U64_C(1)}, // Domain size is small but min/max * 10^precision loses precision. {.value = 900719925474099.6, .max = OPT_DOUBLE_C(900719925474100.0), .min = OPT_DOUBLE_C(900719925474099.0), .precision = OPT_I32_C(1), .expectError = "Invalid upper bound for double precision. Absolute"}, {.value = -900719925474099.6, .max = OPT_DOUBLE_C(-900719925474099.0), .min = OPT_DOUBLE_C(-900719925474100.0), .precision = OPT_I32_C(1), .expectError = "Invalid lower bound for double precision. Absolute"}, // 2^52 // The expected values increase by 4503599627370496 * 2^(i-52) + j // i.e. the gaps between integers as the exponent increases since doubles lose precision as // the exponent increases {.value = 0, .max = OPT_DOUBLE_C(4503599627370496), .min = OPT_DOUBLE_C(-4503599627370496), .precision = OPT_I32_C(0), .expect = 0, // Applying min/max/precision result in a domain needing >= 53 bits to represent. // For range v2, expect an error. .expectError = "The domain of double values specified by the min"}, /* Test cases copied from Double_Bounds_Precision ... end */ {.value = -1, .min = OPT_DOUBLE_C(0), .max = OPT_DOUBLE_C(200), .precision = OPT_I32_C(1), .expectError = "greater than or equal to the minimum value"}, {.value = -1, .min = OPT_DOUBLE_C(0), .max = OPT_DOUBLE_C(201), .precision = OPT_I32_C(1), .expectError = "less than or equal to the maximum value"}, {// Expect error due to precision exceeding INT32_MAX. .value = 1, .min = OPT_DOUBLE_C(1), .max = OPT_DOUBLE_C(2), .precision = OPT_I32_C(-1), .expectError = "Precision must be non-negative"}, {// Expect error due to precision exceeding max finite double. // The largest double value is 1.7976931348623157x10^308. 10^309 results in infinity. .value = 1, .min = OPT_DOUBLE_C(0), .max = OPT_DOUBLE_C(1), .precision = OPT_I32_C(309), .expectError = "Precision is too large"}}; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { DoubleTest *test = tests + i; mongocrypt_status_t *const status = mongocrypt_status_new(); if (test->min.set && test->max.set && test->precision.set) { printf("_test_RangeTest_Encode_Double: value=%f, min=%f, max=%f, " "precision=%" PRIu32 "\n", test->value, test->min.value, test->max.value, test->precision.value); } else { printf("_test_RangeTest_Encode_Double: value=%f\n", test->value); } const bool use_range_v2 = !test->use_range_v1; mc_OSTType_Double got; const bool ok = mc_getTypeInfoDouble((mc_getTypeInfoDouble_args_t){.value = test->value, .min = test->min, .max = test->max, .precision = test->precision}, &got, status, use_range_v2); if (test->expectError) { ASSERT_OR_PRINT_MSG(!ok, "expected error, but got none"); ASSERT_STATUS_CONTAINS(status, test->expectError); } else { ASSERT_OK_STATUS(ok, status); ASSERT_CMPUINT64(got.value, ==, test->expect); ASSERT_CMPUINT64(got.min, ==, 0); ASSERT_CMPUINT64(got.max, ==, test->expectMax.set ? test->expectMax.value : UINT64_MAX); } mongocrypt_status_destroy(status); } } #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT typedef struct { mc_dec128 value; mc_optional_dec128_t min; mc_optional_dec128_t max; mc_optional_int32_t precision; mlib_int128 expect; const char *expectError; bool use_range_v1; // By default, use range v2. } Decimal128Test; static void _test_canUsePrecisionModeDecimal(_mongocrypt_tester_t *tester) { #define CAN_USE_PRECISION_MODE(lb, ub, prc, expected, expected_bits_out) \ { \ uint32_t bits_out = 0; \ mongocrypt_status_t *const status = mongocrypt_status_new(); \ printf("_test_canUsePrecisionModeDecimal, min: %s, max: %s, prc: %" PRIu32, \ mc_dec128_to_string(lb).str, \ mc_dec128_to_string(ub).str, \ prc); \ bool result = mc_canUsePrecisionModeDecimal(lb, ub, prc, &bits_out, status); \ ASSERT_OK_STATUS(mongocrypt_status_ok(status), status); \ ASSERT(result == expected); \ ASSERT_CMPINT32(expected_bits_out, ==, bits_out); \ mongocrypt_status_destroy(status); \ } #define CAN_USE_PRECISION_MODE_ERRORS(lb, ub, prc, error) \ { \ mongocrypt_status_t *const status = mongocrypt_status_new(); \ printf("_test_canUsePrecisionModeDecimal errors, min: %s, max: %s, prc: %" PRIu32, \ mc_dec128_to_string(lb).str, \ mc_dec128_to_string(ub).str, \ prc); \ uint32_t bits_out = 0; \ bool result = mc_canUsePrecisionModeDecimal(lb, ub, prc, &bits_out, status); \ ASSERT_OR_PRINT_MSG(!result, "expected error, but got none"); \ ASSERT_STATUS_CONTAINS(status, error); \ mongocrypt_status_destroy(status); \ } CAN_USE_PRECISION_MODE(MC_DEC128(1), MC_DEC128(16), 0, true, 4); CAN_USE_PRECISION_MODE(MC_DEC128(0), MC_DEC128(16), 0, true, 5); // It is unclear where Decimal128 looses precision, so we choose an arbitrarily large value // and make sure that max_bits is correct for that boundary. CAN_USE_PRECISION_MODE(MC_DEC128(1), mc_dec128_from_string("324518553658426726783156020576256"), 0, true, 108); CAN_USE_PRECISION_MODE(MC_DEC128(0), mc_dec128_from_string("324518553658426726783156020576256"), 0, true, 109); CAN_USE_PRECISION_MODE(mc_dec128_from_string("-100000000000000000000000000000000"), mc_dec128_from_string("170141183460469231731687303715880000000"), 0, false, 128); CAN_USE_PRECISION_MODE_ERRORS(mc_dec128_from_string("788545.12392843"), mc_dec128_from_string("4607431769000000.129834923"), 4, "Invalid upper bound for Decimal128 precision. Fractional digits"); CAN_USE_PRECISION_MODE_ERRORS(mc_dec128_from_string("788545.12392843"), mc_dec128_from_string("7885451.2"), 4, "Invalid lower bound for Decimal128 precision. Fractional digits"); CAN_USE_PRECISION_MODE_ERRORS(mc_dec128_from_string("324518553658426726783156020576256"), mc_dec128_from_string("340282366920938463463374607431768211455"), 10, "Invalid upper bound for Decimal128 precision. Absolute scaled"); CAN_USE_PRECISION_MODE_ERRORS(mc_dec128_from_string("-340282366920938463463374607431768211455"), mc_dec128_from_string("-3245185536584267267831560"), 10, "Invalid lower bound for Decimal128 precision. Absolute scaled"); CAN_USE_PRECISION_MODE_ERRORS(mc_dec128_from_string("-17014118346046923173168730371588.0000000"), mc_dec128_from_string("17014118346046923173168730371588.0000000"), 7, "Invalid value for precision"); CAN_USE_PRECISION_MODE_ERRORS(MC_DEC128(788545.000000), mc_dec128_from_string("340282366920938463463374607431769000000.000000"), 0, "Invalid upper bound for Decimal128 precision. Absolute scaled"); #undef CAN_USE_PRECISION_MODE #undef CAN_USE_PRECISION_MODE_ERRORS } static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { Decimal128Test tests[] = { #define CASE(Value, ExpectStr) \ (Decimal128Test){.value = mc_dec128_from_string(#Value), .expect = mlib_int128_from_string(ExpectStr, NULL)} /* Test cases copied from server Decimal128_Bounds test ... begin */ // Larger numbers map to larger int128 CASE(-1234567890E7, "108549948892579231731687303715884111887"), CASE(-1234567890E6, "108559948892579231731687303715884111886"), CASE(-1234567890E5, "108569948892579231731687303715884111885"), CASE(-1234567890E4, "108579948892579231731687303715884111884"), CASE(-1234567890E3, "108589948892579231731687303715884111883"), CASE(-1234567890E2, "108599948892579231731687303715884111882"), CASE(-1234567890E1, "108609948892579231731687303715884111881"), CASE(-123456789012345, "108569948892579108281687303715884111885"), CASE(-12345678901234, "108579948892579108331687303715884111884"), CASE(-1234567890123, "108589948892579108731687303715884111883"), CASE(-123456789012, "108599948892579111731687303715884111882"), CASE(-12345678901, "108609948892579131731687303715884111881"), CASE(-1234567890, "108619948892579231731687303715884111880"), CASE(-99999999, "108631183460569231731687303715884111878"), CASE(-8888888, "108642294572469231731687303715884111877"), CASE(-777777, "108653405690469231731687303715884111876"), CASE(-66666, "108664516860469231731687303715884111875"), CASE(-5555, "108675628460469231731687303715884111874"), CASE(-444, "108686743460469231731687303715884111873"), CASE(-334, "108687843460469231731687303715884111873"), CASE(-333, "108687853460469231731687303715884111873"), CASE(-44, "108696783460469231731687303715884111872"), CASE(-33, "108697883460469231731687303715884111872"), CASE(-22, "108698983460469231731687303715884111872"), CASE(-5, "108706183460469231731687303715884111871"), CASE(-4, "108707183460469231731687303715884111871"), CASE(-3, "108708183460469231731687303715884111871"), CASE(-2, "108709183460469231731687303715884111871"), CASE(-1, "108710183460469231731687303715884111871"), CASE(0, "170141183460469231731687303715884105728"), CASE(1, "231572183460469231731687303715884099585"), CASE(2, "231573183460469231731687303715884099585"), CASE(3, "231574183460469231731687303715884099585"), CASE(4, "231575183460469231731687303715884099585"), CASE(5, "231576183460469231731687303715884099585"), CASE(22, "231583383460469231731687303715884099584"), CASE(33, "231584483460469231731687303715884099584"), CASE(44, "231585583460469231731687303715884099584"), CASE(333, "231594513460469231731687303715884099583"), CASE(334, "231594523460469231731687303715884099583"), CASE(444, "231595623460469231731687303715884099583"), CASE(5555, "231606738460469231731687303715884099582"), CASE(66666, "231617850060469231731687303715884099581"), CASE(777777, "231628961230469231731687303715884099580"), CASE(8888888, "231640072348469231731687303715884099579"), CASE(33E56, "232144483460469231731687303715884099528"), CASE(22E57, "232153383460469231731687303715884099527"), CASE(11E58, "232162283460469231731687303715884099526"), // Smaller exponents map to smaller int128 CASE(1E-6, "231512183460469231731687303715884099591"), CASE(1E-7, "231502183460469231731687303715884099592"), CASE(1E-8, "231492183460469231731687303715884099593"), CASE(1E-56, "231012183460469231731687303715884099641"), CASE(1E-57, "231002183460469231731687303715884099642"), CASE(1E-58, "230992183460469231731687303715884099643"), // Smaller negative exponents map to smaller int128 CASE(-1E-6, "108770183460469231731687303715884111865"), CASE(-1E-7, "108780183460469231731687303715884111864"), CASE(-1E-8, "108790183460469231731687303715884111863"), CASE(-1E-56, "109270183460469231731687303715884111815"), CASE(-1E-57, "109280183460469231731687303715884111814"), CASE(-1E-58, "109290183460469231731687303715884111813"), // Larger exponents map to larger int128 CASE(-33E56, "108137883460469231731687303715884111928"), CASE(-22E57, "108128983460469231731687303715884111929"), CASE(-11E58, "108120083460469231731687303715884111930"), (Decimal128Test){.value = MC_DEC128_LARGEST_POSITIVE, .expect = mlib_int128_from_string("293021183460469231731687303715884093440", NULL)}, (Decimal128Test){.value = MC_DEC128_SMALLEST_POSITIVE, .expect = mlib_int128_from_string("170141183460469231731687303715884105729", NULL)}, (Decimal128Test){.value = MC_DEC128_LARGEST_NEGATIVE, .expect = mlib_int128_from_string("47261183460469231731687303715884118016", NULL)}, (Decimal128Test){.value = MC_DEC128_SMALLEST_NEGATIVE, .expect = mlib_int128_from_string("170141183460469231731687303715884105727", NULL)}, (Decimal128Test){.value = MC_DEC128_NORMALIZED_ZERO, .expect = mlib_int128_from_string("170141183460469231731687303715884105728", NULL)}, (Decimal128Test){.value = MC_DEC128_NEGATIVE_EXPONENT_ZERO, .expect = mlib_int128_from_string("170141183460469231731687303715884105728", NULL)}, /* Test cases copied from server Decimal128_Bounds test ... end */ #define ERROR_CASE(Value, Min, Max, Precision, ErrorString) \ (Decimal128Test){ \ .value = Value, \ .min = Min, \ .max = Max, \ .precision = Precision, \ .expectError = ErrorString, \ } ERROR_CASE(MC_DEC128_C(1), OPT_NULLOPT, OPT_MC_DEC128(MC_DEC128_C(2)), OPT_I32(5), "min, max, and precision must all be set or must all be unset"), ERROR_CASE(MC_DEC128_C(1), OPT_MC_DEC128(MC_DEC128_C(0)), OPT_NULLOPT, OPT_I32(5), "min, max, and precision must all be set or must all be unset"), ERROR_CASE(MC_DEC128_C(1), OPT_MC_DEC128(MC_DEC128_C(2)), OPT_MC_DEC128(MC_DEC128_C(1)), OPT_I32(5), "The minimum value must be less than the maximum value"), ERROR_CASE(MC_DEC128_C(1), OPT_MC_DEC128(MC_DEC128_C(2)), OPT_MC_DEC128(MC_DEC128_C(3)), OPT_I32(5), "Value must be greater than or equal to the minimum value " "and less than or equal to the maximum value"), ERROR_CASE(MC_DEC128_C(4), OPT_MC_DEC128(MC_DEC128_C(2)), OPT_MC_DEC128(MC_DEC128_C(3)), OPT_I32(5), "Value must be greater than or equal to the minimum value " "and less than or equal to the maximum value"), ERROR_CASE(MC_DEC128_POSITIVE_INFINITY, OPT_NULLOPT, OPT_NULLOPT, OPT_NULLOPT, "Infinity and Nan Decimal128 values are not supported."), ERROR_CASE(MC_DEC128_NEGATIVE_INFINITY, OPT_NULLOPT, OPT_NULLOPT, OPT_NULLOPT, "Infinity and Nan Decimal128 values are not supported."), ERROR_CASE(MC_DEC128_POSITIVE_NAN, OPT_NULLOPT, OPT_NULLOPT, OPT_NULLOPT, "Infinity and Nan Decimal128 values are not supported."), ERROR_CASE(MC_DEC128_NEGATIVE_NAN, OPT_NULLOPT, OPT_NULLOPT, OPT_NULLOPT, "Infinity and Nan Decimal128 values are not supported."), /* Test cases copied from Decimal128_Bounds_Precision ... begin */ #define ASSERT_EIBP(Value, Precision, Expect) \ (Decimal128Test){ \ .value = mc_dec128_from_string(Value), \ .min = OPT_MC_DEC128(MC_DEC128_C(-100000)), \ .max = OPT_MC_DEC128(MC_DEC128_C(100000)), \ .precision = OPT_I32(Precision), \ .expect = MLIB_INT128(Expect), \ } ASSERT_EIBP("3.141592653589E-1", 10, 1000003141592653), ASSERT_EIBP("31.41592653589E-2", 10, 1000003141592653), ASSERT_EIBP("314.1592653589E-3", 10, 1000003141592653), ASSERT_EIBP("3141.592653589E-4", 10, 1000003141592653), ASSERT_EIBP("31415.92653589E-5", 10, 1000003141592653), ASSERT_EIBP("314159.2653589E-6", 10, 1000003141592653), ASSERT_EIBP("3141592.653589E-7", 10, 1000003141592653), ASSERT_EIBP("31415926.53589E-8", 10, 1000003141592653), #undef ASSERT_EIBP #define ASSERT_EIBPL(Value, Precision, Expect) \ (Decimal128Test){ \ .value = mc_dec128_from_string(Value), \ .min = OPT_MC_DEC128(MC_DEC128_C(-100000)), \ .max = OPT_MC_DEC128(mc_dec128_from_string("1E22")), \ .precision = OPT_I32(Precision), \ .expect = mlib_int128_from_string(Expect, NULL), \ } ASSERT_EIBPL("3.1415926535897932384626433832795E20", 5, "31415926535897942384626433"), ASSERT_EIBPL("3.1415926535897932384626433832795E20", 6, "314159265358979423846264338"), ASSERT_EIBPL("3.1415926535897932384626433832795E20", 7, "3141592653589794238462643383"), ASSERT_EIBPL("3.1415926535897932384626433832795E20", 8, "31415926535897942384626433832"), #undef ASSERT_EIBPL #define ASSERT_EIBP(Value, Precision, Expect) \ (Decimal128Test){ \ .value = mc_dec128_from_string(#Value), \ .min = OPT_MC_DEC128(MC_DEC128_C(-100000)), \ .max = OPT_MC_DEC128(MC_DEC128_C(100000)), \ .precision = OPT_I32(Precision), \ .expect = MLIB_INT128_CAST(Expect), \ } ASSERT_EIBP(3.141592653589, 1, 1000031), ASSERT_EIBP(3.141592653589, 2, 10000314), ASSERT_EIBP(3.141592653589, 3, 100003141), ASSERT_EIBP(3.141592653589, 4, 1000031415), ASSERT_EIBP(3.141592653589, 5, 10000314159), ASSERT_EIBP(3.141592653589, 6, 100003141592), ASSERT_EIBP(3.141592653589, 7, 1000031415926), #undef ASSERT_EIBP #define ASSERT_EIBB(Val, Max, Min, Precision, Expect) \ (Decimal128Test){ \ .value = mc_dec128_from_string(#Val), \ .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), \ .precision = OPT_I32(Precision), \ .expect = MLIB_INT128_CAST(Expect), \ } // ASSERT_EIBB_OVERFLOW defines cases where applying min/max/precision result in a domain needing >= 128 bits. // For range v1, expect precision to be ignored. // For range v2, expect an error. #define ASSERT_EIBB_OVERFLOW(Val, Max, Min, Precision, Expect) \ (Decimal128Test){ \ .value = mc_dec128_from_string(#Val), \ .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), \ .precision = OPT_I32(Precision), \ .expect = Expect, \ .use_range_v1 = true, \ }, \ (Decimal128Test) { \ .value = mc_dec128_from_string(#Val), .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), .precision = OPT_I32(Precision), \ .expectError = "The domain of decimal values specified by the min, max, and precision " \ "cannot be represented in fewer than 128 bits" \ } #define ASSERT_EIBB_ERROR(Val, Max, Min, Precision, Expect, Error) \ (Decimal128Test){ \ .value = mc_dec128_from_string(#Val), \ .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), \ .precision = OPT_I32(Precision), \ .expect = Expect, \ .use_range_v1 = true, \ }, \ (Decimal128Test) { \ .value = mc_dec128_from_string(#Val), .min = OPT_MC_DEC128(mc_dec128_from_string(#Min)), \ .max = OPT_MC_DEC128(mc_dec128_from_string(#Max)), .precision = OPT_I32(Precision), .expectError = Error \ } ASSERT_EIBB(0, 1, -1, 3, 1000), ASSERT_EIBB(0, 1, -1E5, 3, 100000000), ASSERT_EIBB(-1E-33, 1, -1E5, 3, 100000000), ASSERT_EIBB_ERROR(0, MC_DEC128_LARGEST_POSITIVE, MC_DEC128_LARGEST_NEGATIVE, 3, mlib_int128_from_string("170141183460469231731687303715884105728", NULL), "Invalid upper bound for Decimal128 precision. Max is infinite."), ASSERT_EIBB_ERROR(0, DBL_MAX, DBL_MIN, 3, mlib_int128_from_string("170141183460469231731687303715884105728", NULL), "Invalid upper bound for Decimal128 precision. Max is infinite."), ASSERT_EIBB(3.141592653589, 5, 0, 0, 3), ASSERT_EIBB(3.141592653589, 5, 0, 1, 31), ASSERT_EIBB(3.141592653589, 5, 0, 2, 314), ASSERT_EIBB(3.141592653589, 5, 0, 3, 3141), ASSERT_EIBB(3.141592653589, 5, 0, 16, 31415926535890000), ASSERT_EIBB(-5, -1, -10, 3, 5000), ASSERT_EIBB_ERROR(1E100, DBL_MAX, DBL_MIN, 3, mlib_int128_from_string("232572183460469231731687303715884099485", NULL), "Invalid upper bound for Decimal128 precision. Max is infinite."), ASSERT_EIBB(1E9, 1E10, 0, 3, 1000000000000), ASSERT_EIBB(1E9, 1E10, 0, 0, 1000000000), ASSERT_EIBB(-5, 10, -10, 0, 5), ASSERT_EIBB(-5, 10, -10, 2, 500), ASSERT_EIBB(5E-30, 10E-30, 1E-30, 35, 400000), // Test a range that requires > 64 bits. ASSERT_EIBB(5, 18446744073709551616, .1, 1, 49), #undef ASSERT_EIBB #undef ASSERT_EIBB_OVERFLOW #undef ASSERT_EIBB_ERROR /* Test cases copied from Decimal128_Bounds_Precision ... end */ {// Expect error due to precision exceeding INT32_MAX. .min = OPT_MC_DEC128(MC_DEC128_C(1)), .max = OPT_MC_DEC128(MC_DEC128_C(2)), .precision = OPT_I32(-1), .expectError = "Precision must be non-negative"}, {// Expect error due to precision exceeding max finite Decimal128. // The largest decimal128 value is 9.99999...x10^6144. 10^6145 results in infinity. .min = OPT_MC_DEC128(MC_DEC128_C(0)), .max = OPT_MC_DEC128(MC_DEC128_C(1)), .precision = OPT_I32(6145), .expectError = "Precision is too large"}}; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { Decimal128Test *test = tests + i; mongocrypt_status_t *const status = mongocrypt_status_new(); if (test->min.set && test->max.set && test->precision.set) { printf("_test_RangeTest_Encode_Decimal128: value=%s, min=%s, max=%s, " "precision=%" PRIu32 "\n", mc_dec128_to_string(test->value).str, mc_dec128_to_string(test->min.value).str, mc_dec128_to_string(test->max.value).str, test->precision.value); } else { printf("_test_RangeTest_Encode_Decimal128: value=%s\n", mc_dec128_to_string(test->value).str); } fflush(stdout); mc_OSTType_Decimal128 got; const bool use_range_v2 = !test->use_range_v1; const bool ok = mc_getTypeInfoDecimal128( (mc_getTypeInfoDecimal128_args_t){ .value = test->value, .min = test->min, .max = test->max, .precision = test->precision, }, &got, status, use_range_v2); if (test->expectError) { ASSERT_OR_PRINT_MSG(!ok, "expected error, but got none"); ASSERT_STATUS_CONTAINS(status, test->expectError); } else { ASSERT_OK_STATUS(ok, status); ASSERT_CMPINT128_EQ(got.value, test->expect); ASSERT_CMPINT128_EQ(got.min, MLIB_INT128(0)); } mongocrypt_status_destroy(status); } } #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT void _mongocrypt_tester_install_range_encoding(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_RangeTest_Encode_Int32); INSTALL_TEST(_test_RangeTest_Encode_Int64); INSTALL_TEST(_test_canUsePrecisionModeDouble); INSTALL_TEST(_test_RangeTest_Encode_Double); #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT INSTALL_TEST(_test_canUsePrecisionModeDecimal); INSTALL_TEST(_test_RangeTest_Encode_Decimal128); #endif }