diff --git a/README.maint.md b/README.maint.md index babe023..b1d8060 100644 --- a/README.maint.md +++ b/README.maint.md @@ -13,8 +13,9 @@ derived from `libmongocrypt` version as described below. , and unpack it to `ext/libmongocrypt/libmongocrypt`. 4. Update the SBOM lite file by running `etc/update-sbom.sh` -5. Commit the changes including the new shared library. -6. Create a PR for the changes. Once approved and merged, run the "Release" action on GitHub to create and publish the new gem. +5. Test the changes by running `gem build *.gemspec && gem install libmongocrypt-helper-VERSION.gem`. +6. Commit the changes. +7. Create a PR for the changes. Once approved and merged, run the "Release" action on GitHub to create and publish the new gem. ## Helper Version Scheme diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/benchmark-java.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/benchmark-java.sh new file mode 100755 index 0000000..5c1ea0f --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/benchmark-java.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +. "$(dirname "${BASH_SOURCE[0]}")/init.sh" + +if test "$OS_NAME" != "linux"; then + log "Warning: Script is expected only to run on distro: rhel90-dbx-perf-large" + log "More changes may be needed to run on other distros."; +fi + +MONGOCRYPT_INSTALL_PREFIX=$LIBMONGOCRYPT_DIR/.install + +# Install libmongocrypt. +build_dir="$LIBMONGOCRYPT_DIR/cmake-build" +run_cmake \ + -DCMAKE_INSTALL_PREFIX="$MONGOCRYPT_INSTALL_PREFIX" \ + -DCMAKE_BUILD_TYPE="RelWithDebInfo" \ + -B"$build_dir" +run_cmake --build "$build_dir" --target install + +# Run Java benchmarks. Do not use JDK 8 to avoid hang in gradle observed in MONGOCRYPT-590. +export JAVA_HOME=/opt/java/jdk17 +# Include path to installed libmongocrypt.so +export LD_LIBRARY_PATH="$MONGOCRYPT_INSTALL_PREFIX/lib64" +cd bindings/java/mongocrypt +./gradlew --version +./gradlew clean benchmarks:run --info diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/benchmark-python.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/benchmark-python.sh new file mode 100755 index 0000000..d44a755 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/benchmark-python.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +. "$(dirname "${BASH_SOURCE[0]}")/init.sh" + +if test "$OS_NAME" != "linux"; then + log "Warning: Script is expected only to run on distro: rhel90-dbx-perf-large" + log "More changes may be needed to run on other distros."; +fi + +MONGOCRYPT_INSTALL_PREFIX=$LIBMONGOCRYPT_DIR/.install + +# Install libmongocrypt. +build_dir="$LIBMONGOCRYPT_DIR/cmake-build" +run_cmake \ + -DCMAKE_INSTALL_PREFIX="$MONGOCRYPT_INSTALL_PREFIX" \ + -DCMAKE_BUILD_TYPE="RelWithDebInfo" \ + -B"$build_dir" +run_cmake --build "$build_dir" --target install + +# Run Python benchmarks. +# Include path to installed libmongocrypt.so +export LD_LIBRARY_PATH="$MONGOCRYPT_INSTALL_PREFIX/lib64" +cd bindings/python/ + +/opt/mongodbtoolchain/v4/bin/python3 -m venv venv +. ./venv/bin/activate +python -m pip install --prefer-binary -r requirements-test.txt +python -m pip install -e . + +export OUTPUT_FILE=results.json + +python test/performance/perf_test.py -v diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/config.yml b/ext/libmongocrypt/libmongocrypt/.evergreen/config.yml index 020a46a..8a5da1e 100755 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/config.yml +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/config.yml @@ -95,6 +95,8 @@ functions: "PACKAGER_ARCH=${packager_arch}" \ ${compile_env|} \ bash libmongocrypt/.evergreen/create-packages-and-repos.sh + + "upload packages and repos": - command: archive.targz_pack params: target: libmongocrypt-distro-packages.tar.gz @@ -134,39 +136,55 @@ functions: export MONGOCRYPT_DIR="$(pwd)/all/${variant_name}" cd ./libmongocrypt/bindings/python && ${test_env|} ./.evergreen/test.sh - "build and test node": - - command: "subprocess.exec" + "test python integ": + - command: subprocess.exec + params: + binary: bash + include_expansions_in_env: + - project_directory + - variant_name + args: + - ./libmongocrypt/bindings/python/.evergreen/integ-setup.sh + - command: expansions.update + params: + file: expansion.yml + - command: subprocess.exec + params: + binary: bash + background: true + args: + - ${DRIVERS_TOOLS}/.evergreen/csfle/start-servers.sh + - command: subprocess.exec params: binary: bash - working_dir: "./libmongocrypt/bindings/node" args: - - "./.evergreen/test.sh" + - ${DRIVERS_TOOLS}/.evergreen/csfle/await-servers.sh + - command: subprocess.exec + params: + binary: bash env: - PROJECT_DIRECTORY: ${project_directory} - NODE_GITHUB_TOKEN: ${node_github_token} - DISTRO_ID: ${distro_id} - BUILD_VARIANT: ${build_variant} - NODE_NVM_USE_VERSION: ${nvm_use_version|18} - - "build and test node no peer dependencies": + TOPOLOGY: replica_set + args: + - ${DRIVERS_TOOLS}/.evergreen/run-orchestration.sh - command: "subprocess.exec" params: binary: bash - working_dir: "./libmongocrypt/bindings/node" + include_expansions_in_env: + - DRIVERS_TOOLS + - PYMONGO_DIR + - MONGOCRYPT_DIR args: - - "./.evergreen/test.sh" - env: - PROJECT_DIRECTORY: ${project_directory} - NODE_GITHUB_TOKEN: ${node_github_token} - DISTRO_ID: ${distro_id} - BUILD_VARIANT: ${build_variant} - OMIT_PEER_DEPS: "true" - NODE_NVM_USE_VERSION: ${nvm_use_version|18} - - "attach node xunit results": + - ./libmongocrypt/bindings/python/.evergreen/integ-test.sh + - command: subprocess.exec + params: + binary: bash + include_expansions_in_env: + - DRIVERS_TOOLS + args: + - ./libmongocrypt/bindings/python/.evergreen/integ-teardown.sh - command: attach.xunit_results params: - file: ./libmongocrypt/bindings/node/xunit.xml + file: ${PYMONGO_DIR}/xunit-results/TEST-*.xml "publish java": - command: git.get_project @@ -179,17 +197,19 @@ functions: ./libmongocrypt/.evergreen/print-env-info.sh - command: shell.exec params: + include_expansions_in_env: + - nexus_username + - nexus_password + - signing_password + - signing_keyId + - ring_file_gpg_base64 + script: |- if [ "${is_patch}" = "true" ]; then echo "Patch build detected, skipping" exit 0 fi export PROJECT_DIRECTORY=${project_directory} - export NEXUS_USERNAME=${nexus_username} - export NEXUS_PASSWORD=${nexus_password} - export SIGNING_PASSWORD=${signing_password} - export SIGNING_KEY_ID=${signing_keyId} - export RING_FILE_GPG_BASE64=${ring_file_gpg_base64} cd ./libmongocrypt/bindings/java/mongocrypt && ${test_env|} ./.evergreen/publish.sh "download tarball": @@ -201,15 +221,6 @@ functions: bucket: mciuploads extract_to: all/${variant_name} - "download distro package tarball": - - command: s3.get - params: - aws_key: '${aws_key}' - aws_secret: '${aws_secret}' - remote_file: '${project}/${build_variant}/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt-distro-packages.tar.gz' - bucket: mciuploads - extract_to: libmongocrypt/repo - "setup packaging credentials": - command: shell.exec params: @@ -241,8 +252,50 @@ functions: cat < ~/.notary_env.sh export NOTARY_TOKEN=${repo_notary_secret} export NOTARY_KEY_NAME=${repo_notary_name} + export BARQUE_USERNAME=${barque_username} + export BARQUE_API_KEY=${barque_api_key} EOF + "publish packages": + - command: shell.exec + params: + working_dir: libmongocrypt + shell: bash + script: |- + [ -f ~/.notary_env.sh ] && . ~/.notary_env.sh + set -o xtrace + set -o errexit + set -o verbose + + if [ "${is_patch}" = "true" ]; then + echo "patch build, skipping packaging publication" + exit 0 + fi + + if [ "${has_packages|}" != "true" ] ; then + echo "'has_packages' is not 'true', skipping package publication" + exit 0 + fi + + # Some venv-activate scripts are not nounset-clean + set +u + + # Need requests and poster for notary-client.py + python -m virtualenv venv + cd venv + . bin/activate + ./bin/pip install requests + ./bin/pip install poster + ./bin/pip install pycrypto + cd .. + # Get the current version of libmongocrypt. + pkg_version="$(python etc/calc_release_version.py)" + CURATOR_RELEASE=${curator_release|"e0b5f66fc89ec0acddcd40ea5f447a8300ded2b9"} + curl -L -O http://boxes.10gen.com/build/curator/curator-dist-rhel70-$CURATOR_RELEASE.tar.gz + tar -zxvf curator-dist-rhel70-$CURATOR_RELEASE.tar.gz + ./curator version + ./curator repo submit --config etc/repo_config.yaml --distro ${packager_distro} --edition org --version $pkg_version --arch ${packager_arch} --service https://barque.corp.mongodb.com/ --packages https://mciuploads.s3.amazonaws.com/${project}/${build_variant}/${branch_name}/${libmongocrypt_s3_suffix}/libmongocrypt-distro-packages.tar.gz + "build csharp and test": - command: "shell.exec" params: @@ -254,36 +307,14 @@ functions: bash ./libmongocrypt/.evergreen/build_all.sh env ${compile_env|} bash ./libmongocrypt/.evergreen/compile_cs.sh - "build python release macos": - - command: shell.exec - params: - script: | - set -ex - cd ./libmongocrypt/bindings/python - PYTHON=${PYTHON} MACOS_TARGET=${MACOS_TARGET} ./release.sh - "build python release": - command: shell.exec params: + shell: bash script: | set -ex cd ./libmongocrypt/bindings/python - ./release.sh - - "test python release": - - command: shell.exec - params: - script: | - set -ex - cd ./libmongocrypt/bindings/python - ROOT=$(pwd) - for file in ./dist/*.whl; do - ${PYTHON} -m pip uninstall -y pymongocrypt - ${PYTHON} -m pip install --upgrade --user $file - cd $HOME - ${PYTHON} -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" - cd $ROOT - done + PYTHON=${PYTHON} ./release.sh "upload python release": - command: archive.targz_pack @@ -366,6 +397,30 @@ tasks: - func: "build and test" - func: "tar and upload libmongocrypt libraries" - func: "create packages and repos" + - func: "upload packages and repos" + +- name: build-with-earthly + commands: + - func: "fetch source" + - func: "earthly" + vars: + args: --artifact +build/libmongocrypt-install --env=${earthly_env} ${workdir}/install + - func: "tar and upload libmongocrypt libraries" + +- name: build-deb-packages-with-earthly + commands: + - func: "fetch source" + - func: "earthly" + vars: + args: +create-deb-packages-and-repos --env=${earthly_env} --packager_distro=${packager_distro} --packager_arch=${packager_arch} + - func: "upload packages and repos" + +- name: publish-deb-packages-with-earthly + depends_on: build-deb-packages-with-earthly + commands: + - func: "fetch source" + - func: "setup packaging credentials" + - func: "publish packages" - name: clang-tidy commands: @@ -435,38 +490,33 @@ tasks: - func: "test python" vars: { variant_name: windows-test } -- name: "release-python-macos-1100" - tags: ["release_python_tag"] - run_on: macos-1100 +- name: test-python-integ + depends_on: + - build-and-test-and-upload commands: - func: "fetch source" - - func: "build python release macos" - - func: "test python release" - vars: { PYTHON: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 } - - func: "upload python release" + - func: "download tarball" + vars: { variant_name: "${build_variant}" } + - func: "test python integ" + vars: { variant_name: "${build_variant}" } -- name: "release-python-macos-1014" +- name: "release-python-macos-1100" tags: ["release_python_tag"] - run_on: macos-1014 + run_on: macos-1100 commands: - func: "fetch source" - - func: "build python release macos" - vars: - PYTHON: /Library/Frameworks/Python.framework/Versions/3.7/bin/python3 - MACOS_TARGET: macos_x86_64 - - func: "test python release" - vars: { PYTHON: /Library/Frameworks/Python.framework/Versions/3.7/bin/python3 } + - func: "build python release" + vars: { PYTHON: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 } - func: "upload python release" - name: "release-python-linux" tags: ["release_python_tag"] - run_on: ubuntu2004-small + run_on: ubuntu2004-large exec_timeout_secs: 216000 # 60 minutes (manylinux task is slow). commands: - func: "fetch source" - func: "build python release" - - func: "test python release" - vars: { PYTHON: /opt/python/3.7/bin/python3 } + vars: { PYTHON: /opt/python/3.8/bin/python3 } - func: "upload python release" - name: "release-python-windows" @@ -475,13 +525,12 @@ tasks: commands: - func: "fetch source" - func: "build python release" - - func: "test python release" - vars: { PYTHON: C:/python/Python37/python.exe } + vars: { PYTHON: C:/python/Python38/python.exe } - func: "upload python release" - name: "release-python-combine" tags: ["release_python_tag"] - run_on: ubuntu2004-small + run_on: rhel84-small depends_on: - name: "*" variant: ".release_python_tag" @@ -496,25 +545,6 @@ tasks: vars: test_env: PROJECT_DIRECTORY=${project_directory} -- name: build-and-test-node - commands: - - func: "fetch source" - - func: "build and test node" - - func: "attach node xunit results" - -- name: build-and-test-node-no-peer-dependencies - commands: - - func: "fetch source" - - func: "build and test node no peer dependencies" - - func: "attach node xunit results" - -# Note: keep this disabled unless you want master to force-push -- name: build-and-test-node-force-publish - commands: - - func: "fetch source" - - func: "build and test node" - - func: "attach node xunit results" - - name: publish-java depends_on: - variant: ubuntu2004-64 @@ -607,6 +637,12 @@ tasks: name: build-and-test-and-upload - variant: amazon2-arm64 name: build-and-test-and-upload + - variant: amazon2023 + name: build-and-test-and-upload + - variant: amazon2023-arm64 + name: build-and-test-and-upload + - variant: debian12 + name: build-and-test-and-upload - variant: debian11 name: build-and-test-and-upload - variant: debian10 @@ -621,6 +657,16 @@ tasks: name: build-and-test-and-upload - variant: rhel-80-64-bit name: build-and-test-and-upload + - variant: rhel-81-ppc64el + name: build-and-test-and-upload + - variant: rhel-82-arm64 + name: build-and-test-and-upload + - variant: rhel-83-zseries + name: build-and-test-and-upload + - variant: rhel-91-64-bit + name: build-and-test-and-upload + - variant: rhel-91-arm64 + name: build-and-test-and-upload - variant: suse12-64 name: build-and-test-and-upload - variant: suse15-64 @@ -641,6 +687,10 @@ tasks: name: build-and-test-and-upload - variant: macos name: build-and-test-and-upload + - variant: alpine-amd64-earthly + name: build-with-earthly + - variant: alpine-arm64-earthly + name: build-with-earthly commands: - func: "fetch source" - command: shell.exec @@ -660,6 +710,12 @@ tasks: vars: { variant_name: "amazon2" } - func: "download tarball" vars: { variant_name: "amazon2-arm64" } + - func: "download tarball" + vars: { variant_name: "amazon2023" } + - func: "download tarball" + vars: { variant_name: "amazon2023-arm64" } + - func: "download tarball" + vars: { variant_name: "debian12" } - func: "download tarball" vars: { variant_name: "debian11" } - func: "download tarball" @@ -674,6 +730,16 @@ tasks: vars: { variant_name: "rhel-71-ppc64el" } - func: "download tarball" vars: { variant_name: "rhel-80-64-bit" } + - func: "download tarball" + vars: { variant_name: "rhel-81-ppc64el" } + - func: "download tarball" + vars: { variant_name: "rhel-82-arm64" } + - func: "download tarball" + vars: { variant_name: "rhel-83-zseries" } + - func: "download tarball" + vars: { variant_name: "rhel-91-64-bit" } + - func: "download tarball" + vars: { variant_name: "rhel-91-arm64" } - func: "download tarball" vars: { variant_name: "suse12-64" } - func: "download tarball" @@ -694,6 +760,10 @@ tasks: vars: { variant_name: "ubuntu2204-arm64" } - func: "download tarball" vars: { variant_name: "macos" } + - func: "download tarball" + vars: { variant_name: "alpine-amd64-earthly" } + - func: "download tarball" + vars: { variant_name: "alpine-arm64-earthly" } - command: archive.targz_pack params: target: libmongocrypt-all.tar.gz @@ -742,82 +812,46 @@ tasks: depends_on: build-and-test-and-upload commands: - func: "fetch source" - - func: "download distro package tarball" - func: "setup packaging credentials" - - command: shell.exec - params: - working_dir: libmongocrypt - shell: bash - script: |- - [ -f ~/.notary_env.sh ] && . ~/.notary_env.sh - set -o xtrace - set -o errexit - set -o verbose - - if [ "${is_patch}" = "true" ]; then - echo "patch build, skipping packaging publication" - exit 0 - fi - - if [ "${has_packages|}" != "true" ] ; then - echo "'has_packages' is not 'true', skipping package publication" - exit 0 - fi - - # Some venv-activate scripts are not nounset-clean - set +u - - # Need requests and poster for notary-client.py - python -m virtualenv venv - cd venv - . bin/activate - ./bin/pip install requests - ./bin/pip install poster - ./bin/pip install pycrypto - cd .. - # Get the current version of libmongocrypt. - pkg_version="$(python etc/calc_release_version.py)" - CURATOR_RELEASE=${curator_release|"e0b5f66fc89ec0acddcd40ea5f447a8300ded2b9"} - curl -L -O http://boxes.10gen.com/build/curator/curator-dist-rhel70-$CURATOR_RELEASE.tar.gz - tar -zxvf curator-dist-rhel70-$CURATOR_RELEASE.tar.gz - ./curator version - ./curator repo --config etc/repo_config.yaml --distro ${packager_distro} --edition org --version $pkg_version --arch ${packager_arch} --packages repo - -- name: windows-upload-check - depends_on: build-and-test-and-upload + - func: "publish packages" +- name: windows-upload-release + depends_on: + - variant: windows-test + name: build-and-test-and-upload commands: - func: "fetch source" - command: shell.exec params: + shell: bash working_dir: libmongocrypt script: |- set -o xtrace set -o errexit - CMAKE=/cygdrive/c/cmake/bin/cmake - mongocrypt_version="$(python etc/calc_release_version.py)" - case "$mongocrypt_version" in + . .evergreen/init.sh + libmongocrypt_release_version=$(run_python ./etc/calc_release_version.py) + case "$libmongocrypt_release_version" in *+*) - # Not a tagged release. - echo "{}" > ./.evergreen/windows-upload.json + # Not a tagged release. Use full release version suffix. + upload_suffix="$libmongocrypt_release_version" ;; *-*) - # This is an unstable release, like 1.1.0-beta1 or 1.0.1-rc0 - cp ./.evergreen/windows-upload-doit-unstable.json ./.evergreen/windows-upload.json + # Unstable release, like 1.1.0-beta1 or 1.0.1-rc0. Overwrite the latest unstable URL. + upload_suffix='_unstable' ;; *) - # It is a tagged release. - cp ./.evergreen/windows-upload-doit.json ./.evergreen/windows-upload.json + # Tagged release. Overwrite the latest stable URL. + upload_suffix='' ;; esac - - command: generate.tasks - params: - files: - - libmongocrypt/.evergreen/windows-upload.json -- name: windows-upload - commands: - - command: s3.get + # Add expansions used in later commands: + echo "libmongocrypt_release_version: '$libmongocrypt_release_version'" > expansions.yml + echo "upload_suffix: '$upload_suffix'" >> expansions.yml + - command: expansions.update + params: + file: libmongocrypt/expansions.yml + - command: s3.get # Download Windows build. params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' @@ -842,14 +876,52 @@ tasks: source_dir: libmongocrypt_upload include: [./**] - command: s3.put + # Windows tarballs were previously documented as available from these fixed URLs: + # (stable) : https://s3.amazonaws.com/mciuploads/libmongocrypt/windows/latest_release/libmongocrypt.tar.gz + # (unstable): https://s3.amazonaws.com/mciuploads/libmongocrypt/windows/latest_release/libmongocrypt_unstable.tar.gz + # Documentation now refers to the GitHub release page, which includes the per-release tarball. + # The fixed URL upload is kept to avoid possibly breaking expectations. Consider removing in the future. params: aws_key: '${aws_key}' aws_secret: '${aws_secret}' remote_file: 'libmongocrypt/windows/latest_release/libmongocrypt${upload_suffix}.tar.gz' + display_name: (Deprecated) libmongocrypt${upload_suffix}.tar.gz bucket: mciuploads permissions: public-read local_file: 'libmongocrypt_upload.tar.gz' - content_type: '${content_type|application/x-gzip}' + content_type: 'application/x-gzip' + - command: s3.put # Upload tarball for GitHub Release. + params: + aws_key: '${aws_key}' + aws_secret: '${aws_secret}' + remote_file: '${project}/${build_variant}/${branch_name}/${revision}/${version_id}/libmongocrypt-windows-x86_64-${libmongocrypt_release_version}.tar.gz' + display_name: libmongocrypt-windows-x86_64-${libmongocrypt_release_version}.tar.gz + bucket: mciuploads + permissions: public-read + local_file: 'libmongocrypt_upload.tar.gz' + content_type: 'application/x-gzip' + - command: shell.exec + params: + shell: bash + script: |- + set -o errexit + # Authenticate to artifactory for signing image. + echo "${artifactory_password}" | docker login --password-stdin --username "${artifactory_username}" artifactory.corp.mongodb.com + # Copy file to sign into `libmongocrypt` directory to be used by Earthly. + cp libmongocrypt_upload.tar.gz libmongocrypt + - func: "earthly" # Sign tarball. + vars: + args: --secret garasign_username=${garasign_username} --secret garasign_password=${garasign_password} +sign --file_to_sign=libmongocrypt_upload.tar.gz --output_file=libmongocrypt_upload.asc + - command: s3.put # Upload signature for GitHub Release. + params: + aws_key: '${aws_key}' + aws_secret: '${aws_secret}' + remote_file: '${project}/${build_variant}/${branch_name}/${revision}/${version_id}/libmongocrypt-windows-x86_64-${libmongocrypt_release_version}.asc' + display_name: libmongocrypt-windows-x86_64-${libmongocrypt_release_version}.asc + bucket: mciuploads + permissions: public-read + local_file: 'libmongocrypt/libmongocrypt_upload.asc' + content_type: 'application/pgp-signature' - name: debian-package-build run_on: &deb-package-build-run_on @@ -906,7 +978,7 @@ tasks: - name: rpm-package-build tags: [packaging] run_on: &docker-distros - # * The RHEL76-docker distro runs an old and unsupported version of Docker. + # * The RHEL76-docker distro runs an old and unsupported version of Docker. # * (We requires the --mount parameter) - ubuntu2004-small - ubuntu2004 @@ -930,6 +1002,32 @@ tasks: vars: args: +check-format +- name: benchmark-java + commands: + - func: "fetch source" + - command: "subprocess.exec" + params: + binary: bash + working_dir: "./libmongocrypt" + args: + - "./.evergreen/benchmark-java.sh" + - command: "perf.send" + params: + file: libmongocrypt/bindings/java/mongocrypt/benchmarks/results.json + +- name: benchmark-python + commands: + - func: "fetch source" + - command: "subprocess.exec" + params: + binary: bash + working_dir: "./libmongocrypt" + args: + - "./.evergreen/benchmark-python.sh" + - command: "perf.send" + params: + file: libmongocrypt/bindings/python/results.json + pre: # Update the evergreen expansion to dynamically set the ${libmongocrypt_s3_suffix} and ${libmongocrypt_s3_suffix_copy} expansions. - command: "shell.exec" @@ -977,13 +1075,10 @@ buildvariants: has_packages: true packager_distro: ubuntu1604 packager_arch: x86_64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: @@ -995,10 +1090,7 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan-mac - - build-and-test-node - - build-and-test-node-no-peer-dependencies - - build-and-test-csharp - - test-python + # - build-and-test-csharp // temporary removed to make strong named release. - test-java - name: rhel72-zseries-test display_name: "RHEL 7.2 on zSeries" @@ -1039,11 +1131,8 @@ buildvariants: tasks: - build-and-test-and-upload - build-and-test-shared-bson - - build-and-test-csharp - - build-and-test-node - - build-and-test-node-no-peer-dependencies + # - build-and-test-csharp // temporary removed to make strong named release. - test-java - - windows-upload-check - name: windows-test-python display_name: "Windows Python" run_on: windows-64-vsMulti-small @@ -1062,12 +1151,9 @@ buildvariants: has_packages: true packager_distro: amazon packager_arch: x86_64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: @@ -1079,13 +1165,10 @@ buildvariants: has_packages: true packager_distro: amazon2 packager_arch: x86_64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: @@ -1096,19 +1179,40 @@ buildvariants: expansions: has_packages: true packager_distro: amazon2 - packager_arch: arm64 - nvm_use_version: 16 + packager_arch: aarch64 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies + - name: publish-packages + distros: + - rhel70-small +- name: amazon2023 + display_name: "Amazon Linux 2023" + run_on: amazon2023.0-small + expansions: + has_packages: true + packager_distro: amazon2023 + packager_arch: x86_64 + tasks: + - build-and-test-and-upload + - name: publish-packages + distros: + - rhel70-small +- name: amazon2023-arm64 + display_name: "Amazon Linux 2023 (arm64)" + run_on: amazon2023-arm64-small + expansions: + has_packages: true + packager_distro: amazon2023 + packager_arch: aarch64 + tasks: + - build-and-test-and-upload - name: publish-packages distros: - rhel70-small - name: debian11 - display_name: "Debian 11.0" + display_name: "Debian 11" run_on: debian11-large expansions: has_packages: true @@ -1118,14 +1222,25 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: - ubuntu2004-small +- name: debian12 + display_name: "Debian 12" + run_on: debian12-large + expansions: + has_packages: true + packager_distro: debian12 + packager_arch: x86_64 + python: python3 + tasks: + - build-and-test-and-upload + - name: publish-packages + distros: + - ubuntu2004-small - name: debian10 - display_name: "Debian 10.0" + display_name: "Debian 10" run_on: debian10-test expansions: has_packages: true @@ -1135,8 +1250,6 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: @@ -1148,13 +1261,10 @@ buildvariants: has_packages: true packager_distro: debian92 packager_arch: x86_64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: @@ -1180,13 +1290,9 @@ buildvariants: has_packages: true packager_distro: rhel70 packager_arch: x86_64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - - build-and-test-node - - build-and-test-node-no-peer-dependencies - - test-python - test-java - name: publish-packages distros: @@ -1215,9 +1321,71 @@ buildvariants: tasks: - build-and-test-and-upload - build-and-test-shared-bson - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java + - test-python + - test-python-integ + - name: publish-packages + distros: + - rhel70-small +- name: rhel-82-arm64 + display_name: "RHEL 8.2 arm64" + run_on: rhel82-arm64-small + expansions: + has_packages: true + packager_distro: rhel82 + packager_arch: aarch64 + tasks: + - build-and-test-and-upload + - test-python + - test-python-integ + - name: publish-packages + distros: + - rhel70-small +- name: rhel-81-ppc64el + display_name: "RHEL 8.1 ppc64el" + run_on: rhel81-power8-small + expansions: + has_packages: true + packager_distro: rhel81 + packager_arch: ppc64le + tasks: + - build-and-test-and-upload + - name: publish-packages + distros: + - rhel70-small +- name: rhel-83-zseries + display_name: "RHEL 8.3 zSeries" + run_on: rhel83-zseries-small + expansions: + has_packages: true + packager_distro: rhel83 + packager_arch: s390x + tasks: + - build-and-test-and-upload + - name: publish-packages + distros: + - rhel70-small +- name: rhel-91-64-bit + display_name: "RHEL 9.1 64-bit" + run_on: rhel91-small + expansions: + has_packages: true + packager_distro: rhel91 + packager_arch: x86_64 + tasks: + - build-and-test-and-upload + - name: publish-packages + distros: + - rhel70-small +- name: rhel-91-arm64 + display_name: "RHEL 9.1 arm64" + run_on: rhel91-arm64-small + expansions: + has_packages: true + packager_distro: rhel91 + packager_arch: aarch64 + tasks: + - build-and-test-and-upload - name: publish-packages distros: - rhel70-small @@ -1228,14 +1396,10 @@ buildvariants: has_packages: true packager_distro: suse12 packager_arch: x86_64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - - test-java - name: publish-packages distros: - rhel70-small @@ -1246,13 +1410,10 @@ buildvariants: has_packages: true packager_distro: suse15 packager_arch: x86_64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: @@ -1264,13 +1425,10 @@ buildvariants: has_packages: true packager_distro: ubuntu1604 packager_arch: arm64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: @@ -1282,14 +1440,11 @@ buildvariants: has_packages: true packager_distro: ubuntu1804 packager_arch: x86_64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - - build-and-test-csharp + # - build-and-test-csharp // temporary removed to make strong named release. - test-java - name: publish-packages distros: @@ -1311,13 +1466,10 @@ buildvariants: has_packages: true packager_distro: ubuntu1804 packager_arch: arm64 - nvm_use_version: 16 tasks: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-java - name: publish-packages distros: @@ -1334,9 +1486,7 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - - build-and-test-csharp + # - build-and-test-csharp // temporary removed to make strong named release. - test-java - upload-java - publish-packages @@ -1351,9 +1501,6 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - - test-java - name: publish-packages distros: - ubuntu2004-small @@ -1370,8 +1517,6 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies # see https://jira.mongodb.org/browse/MONGOCRYPT-515 #- build-and-test-csharp - test-java @@ -1379,6 +1524,7 @@ buildvariants: - name: publish-packages distros: - ubuntu2004-small + - windows-upload-release - name: ubuntu2204-arm64 display_name: "Ubuntu 22.04 arm64" run_on: ubuntu2204-arm64-small @@ -1390,9 +1536,6 @@ buildvariants: - build-and-test-and-upload - build-and-test-shared-bson - build-and-test-asan - - build-and-test-node - - build-and-test-node-no-peer-dependencies - - test-java - name: publish-packages distros: - ubuntu2004-small @@ -1420,8 +1563,6 @@ buildvariants: compile_env: MACOS_UNIVERSAL=ON CMAKE=/opt/homebrew/bin/cmake tasks: - build-and-test-and-upload - - build-and-test-node - - build-and-test-node-no-peer-dependencies - test-python - test-java - name: windows-vs2017-32bit @@ -1434,3 +1575,87 @@ buildvariants: vs_target_arch: x86 tasks: - build-and-test-and-upload + +- name: benchmark + display_name: "Benchmark" + # rhel90-dbx-perf-large is the dedicated performance distro referenced in DRIVERS-2666. + run_on: rhel90-dbx-perf-large + tasks: + - benchmark-java + - benchmark-python + +- name: alpine-amd64-earthly + display_name: "Alpine Linux 3.18 amd64 (via Earthly)" + expansions: + earthly_env: alpine + tasks: + - name: build-with-earthly + run_on: ubuntu2204-small + +- name: alpine-arm64-earthly + display_name: "Alpine Linux 3.18 arm64 (via Earthly)" + expansions: + earthly_env: alpine + tasks: + - name: build-with-earthly + run_on: ubuntu2204-arm64-small + +- name: debian11-arm64-earthly + display_name: "Debian 11 arm64 (via Earthly)" + expansions: + has_packages: true + packager_distro: debian11 + packager_arch: arm64 + earthly_env: deb11 + tasks: + - name: build-deb-packages-with-earthly + # Use an arm64 distro to match the intended target architecture of .deb packages. + run_on: ubuntu2204-arm64-small + - name: publish-deb-packages-with-earthly + # Use a distro suitable for running curator to publish .deb packages. + run_on: ubuntu2004-small + +- name: debian12-arm64-earthly + display_name: "Debian 12 arm64 (via Earthly)" + expansions: + has_packages: true + packager_distro: debian12 + packager_arch: arm64 + earthly_env: deb12 + tasks: + - name: build-deb-packages-with-earthly + # Use an arm64 distro to match the intended target architecture of .deb packages. + run_on: ubuntu2204-arm64-small + - name: publish-deb-packages-with-earthly + # Use a distro suitable for running curator to publish .deb packages. + run_on: ubuntu2004-small + +- name: debian10-arm64-earthly + display_name: "Debian 10 arm64 (via Earthly)" + expansions: + has_packages: true + packager_distro: debian10 + packager_arch: arm64 + earthly_env: deb10 + tasks: + - name: build-deb-packages-with-earthly + # Use an arm64 distro to match the intended target architecture of .deb packages. + run_on: ubuntu2204-arm64-small + - name: publish-deb-packages-with-earthly + # Use a distro suitable for running curator to publish .deb packages. + run_on: ubuntu2004-small + +- name: debian9-arm64-earthly + display_name: "Debian 9 arm64 (via Earthly)" + expansions: + has_packages: true + packager_distro: debian92 + packager_arch: arm64 + earthly_env: deb9 + tasks: + - name: build-deb-packages-with-earthly + # Use an arm64 distro to match the intended target architecture of .deb packages. + run_on: ubuntu2204-arm64-small + - name: publish-deb-packages-with-earthly + # Use a distro suitable for running curator to publish .deb packages. + run_on: ubuntu2004-small diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/create-packages-and-repos.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/create-packages-and-repos.sh index dad208f..0e8a709 100644 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/create-packages-and-repos.sh +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/create-packages-and-repos.sh @@ -46,6 +46,11 @@ tar -zcv -C install \ --exclude=sharedbson \ -f "libmongocrypt-$pkg_version.tar.gz" \ libmongocrypt +pushd "$LIBMONGOCRYPT_DIR/" + (git remote | grep -q upstream) || git remote add upstream https://github.com/mongodb/libmongocrypt + git fetch upstream + git checkout $(git rev-parse upstream/debian/unstable) -- debian +popd pushd "$LIBMONGOCRYPT_DIR/etc/" # The files from libmongocrypt/debian/ are the official maintainer scripts, # but libmongocrypt/etc/debian/ contains a few custom scripts that are diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/debian_package_build.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/debian_package_build.sh index 1e61eb9..f7c9658 100644 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/debian_package_build.sh +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/debian_package_build.sh @@ -39,10 +39,12 @@ on_exit () { trap on_exit EXIT if [ "${IS_PATCH}" = "true" ]; then - git diff HEAD -- . ':!debian' > ../upstream.patch - git diff HEAD -- debian > ../debian.patch + git diff HEAD > ../upstream.patch git clean -fdx git reset --hard HEAD + (git remote | grep -q upstream) || git remote add upstream https://github.com/mongodb/libmongocrypt + git fetch upstream + git checkout $(git rev-parse upstream/debian/unstable) -- debian if [ -s ../upstream.patch ]; then [ -d debian/patches ] || mkdir debian/patches mv ../upstream.patch debian/patches/ @@ -51,13 +53,10 @@ if [ "${IS_PATCH}" = "true" ]; then git commit -m 'Evergreen patch build - upstream changes' git log -n1 -p fi - if [ -s ../debian.patch ]; then - git apply --index ../debian.patch - git commit -m 'Evergreen patch build - Debian packaging changes' - git log -n1 -p - fi fi +export CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)" + cd .. _dbs_args+=(unstable) @@ -66,7 +65,7 @@ git clone https://salsa.debian.org/installer-team/debootstrap.git debootstrap.gi export DEBOOTSTRAP_DIR=`pwd`/debootstrap.git sudo -E ./debootstrap.git/debootstrap "${_dbs_args[@]}" ./unstable-chroot/ http://cdn-aws.deb.debian.org/debian cp -a libmongocrypt ./unstable-chroot/tmp/ -sudo chroot ./unstable-chroot /bin/bash -c "(set -o xtrace && \ +sudo chroot ./unstable-chroot /bin/bash -c '(set -o xtrace && \ apt-get install -y build-essential git-buildpackage fakeroot debhelper cmake curl ca-certificates libssl-dev pkg-config libbson-dev libintelrdfpmath-dev && \ chown -R root:root /tmp/libmongocrypt && \ cd /tmp/libmongocrypt && \ @@ -74,12 +73,21 @@ sudo chroot ./unstable-chroot /bin/bash -c "(set -o xtrace && \ git reset --hard HEAD && \ python3 etc/calc_release_version.py > VERSION_CURRENT && \ git add --force VERSION_CURRENT && \ - git commit VERSION_CURRENT -m 'Set current version' && \ + git commit VERSION_CURRENT -m "Set current version" && \ + (git remote | grep -q upstream) || git remote add upstream https://github.com/mongodb/libmongocrypt + git fetch upstream + git checkout $(git rev-parse upstream/debian/unstable) -- debian LANG=C /bin/bash ./debian/build_snapshot.sh && \ debc ../*.changes && \ dpkg -i ../*.deb && \ - /usr/bin/gcc -I/usr/include/mongocrypt -I/usr/include/libbson-1.0 -o example-state-machine test/example-state-machine.c -lmongocrypt -lbson-1.0 )" + /usr/bin/gcc -I/usr/include/mongocrypt -I/usr/include/libbson-1.0 -o example-state-machine test/example-state-machine.c -lmongocrypt -lbson-1.0 )' [ -e ./unstable-chroot/tmp/libmongocrypt/example-state-machine ] || (echo "Example 'example-state-machine' was not built!" ; exit 1) (cd ./unstable-chroot/tmp/ ; tar zcvf ../../deb.tar.gz *.dsc *.orig.tar.gz *.debian.tar.xz *.build *.deb) +# Build a second time, to ensure a "double build" works +sudo chroot ./unstable-chroot /bin/bash -c "(\ + cd /tmp/libmongocrypt && \ + rm -f example-state-machine && \ + git status --ignored && \ + dpkg-buildpackage -b && dpkg-buildpackage -S )" diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/earthly.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/earthly.sh index 2f838e9..3b66e25 100755 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/earthly.sh +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/earthly.sh @@ -1,10 +1,17 @@ -#!/usr/bin/bash +#!/usr/bin/env bash . "$(dirname "${BASH_SOURCE[0]}")/setup-env.sh" set -euo pipefail -: "${EARTHLY_VERSION:=0.6.30}" +: "${EARTHLY_VERSION:=0.7.8}" + +# Bring in the debian/ directory from the debian/unstable branch +pushd "$(dirname "${BASH_SOURCE[0]}")/../" + (git remote | grep -q upstream) || git remote add upstream https://github.com/mongodb/libmongocrypt + git fetch upstream + git checkout $(git rev-parse upstream/debian/unstable) -- debian +popd # Calc the arch of the executable we want arch="$(uname -m)" @@ -26,6 +33,10 @@ cache_dir="$USER_CACHES_DIR/earthly-sh/$EARTHLY_VERSION" mkdir -p "$cache_dir" exe_filename="earthly-$OS_NAME-$arch$EXE_SUFFIX" +if [[ "$OS_NAME" == "macos" ]]; then + # Earthly downloads use `darwin`. + exe_filename="earthly-darwin-$arch$EXE_SUFFIX" +fi exe_path="$cache_dir/$exe_filename" # Download if it isn't already present diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/init.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/init.sh index ee371e1..8642378 100644 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/init.sh +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/init.sh @@ -230,8 +230,6 @@ run_python() { python3.10 python3.9 python3.8 - python3.7 - python3.6 python3 python ) diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/linker-tests.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/linker-tests.sh index f1f8cb3..222f096 100755 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/linker-tests.sh +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/linker-tests.sh @@ -56,6 +56,8 @@ if is_true USE_NINJA; then fi run_chdir "$MONGOC_DIR" git apply --ignore-whitespace "$linker_tests_deps_root/bson_patches/libbson1.patch" +# Apply patch to fix compile on RHEL 6.2. TODO: try to remove once RHEL 6.2 is dropped (MONGOCRYPT-688). +run_chdir "$MONGOC_DIR" git apply "$LIBMONGOCRYPT_DIR/etc/libbson-remove-GCC-diagnostic-pragma.patch" BUILD_PATH="$MONGOC_DIR/cmake-build" BSON1_INSTALL_PATH="$linker_tests_root/install/bson1" @@ -71,6 +73,8 @@ run_cmake --build "$BUILD_PATH" --target install --config RelWithDebInfo # Prepare libbson2 run_chdir "$MONGOC_DIR" git reset --hard run_chdir "$MONGOC_DIR" git apply --ignore-whitespace "$linker_tests_deps_root/bson_patches/libbson2.patch" +# Apply patch to fix compile on RHEL 6.2. TODO: try to remove once RHEL 6.2 is dropped (MONGOCRYPT-688). +run_chdir "$MONGOC_DIR" git apply "$LIBMONGOCRYPT_DIR/etc/libbson-remove-GCC-diagnostic-pragma.patch" LIBBSON2_SRC_DIR="$MONGOC_DIR" # Build libmongocrypt, static linking against libbson2 diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/prep_c_driver_source.sh b/ext/libmongocrypt/libmongocrypt/.evergreen/prep_c_driver_source.sh index e54a682..dfff60e 100755 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/prep_c_driver_source.sh +++ b/ext/libmongocrypt/libmongocrypt/.evergreen/prep_c_driver_source.sh @@ -3,9 +3,7 @@ set -euxo pipefail # Clone mongo-c-driver and check out to a tagged version. -MONGO_C_DRIVER_VERSION=1.17.0 +MONGO_C_DRIVER_VERSION=1.27.1 # Force checkout with lf endings since .sh must have lf, not crlf on Windows git clone https://github.com/mongodb/mongo-c-driver.git --config core.eol=lf --config core.autocrlf=false --depth=1 --branch $MONGO_C_DRIVER_VERSION -echo $MONGO_C_DRIVER_VERSION > mongo-c-driver/VERSION_CURRENT - diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/windows-upload-doit-unstable.json b/ext/libmongocrypt/libmongocrypt/.evergreen/windows-upload-doit-unstable.json deleted file mode 100644 index bc64b3b..0000000 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/windows-upload-doit-unstable.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "buildvariants": [ - { - "tasks": [ - { - "name": "windows-upload" - } - ], - "display_name": "Windows uploader", - "run_on": [ - "windows-64-vs2017-test" - ], - "name": "windows-uploader", - "expansions": { - "upload_suffix": "_unstable" - } - } - ] -} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/.evergreen/windows-upload-doit.json b/ext/libmongocrypt/libmongocrypt/.evergreen/windows-upload-doit.json deleted file mode 100644 index c91ab2d..0000000 --- a/ext/libmongocrypt/libmongocrypt/.evergreen/windows-upload-doit.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "buildvariants": [ - { - "tasks": [ - { - "name": "windows-upload" - } - ], - "display_name": "Windows uploader", - "run_on": [ - "windows-64-vs2017-test" - ], - "name": "windows-uploader" - } - ] -} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/.git-blame-ignore-revs b/ext/libmongocrypt/libmongocrypt/.git-blame-ignore-revs index da3837a..3a5bcf9 100644 --- a/ext/libmongocrypt/libmongocrypt/.git-blame-ignore-revs +++ b/ext/libmongocrypt/libmongocrypt/.git-blame-ignore-revs @@ -1,2 +1,5 @@ # Mass reformat: d60041a1a863c27bb08c43fe56c2e9588f56d920 + +# Python pre-commit formatting +c03df9ecc60b9d26aa67b72378f0945c1b577b72 \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/.github/dependabot.yml b/ext/libmongocrypt/libmongocrypt/.github/dependabot.yml new file mode 100644 index 0000000..13a3142 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/.github/dependabot.yml @@ -0,0 +1,20 @@ +version: 2 +updates: + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + groups: + actions: + patterns: + - "*" + assignees: + - "@mongodb/dbx-python" + # Python + - package-ecosystem: "pip" + directory: "/bindings/python" + schedule: + interval: "weekly" + assignees: + - "@mongodb/dbx-python" \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/.github/workflows/codeql.yml b/ext/libmongocrypt/libmongocrypt/.github/workflows/codeql.yml new file mode 100644 index 0000000..9c7ef77 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/.github/workflows/codeql.yml @@ -0,0 +1,64 @@ +name: "CodeQL" + +on: + push: + branches: [ "master"] + tags: ['*'] + pull_request: + paths: + - bindings/python/* + - bindings/python/**/*.py + - .github/workflows/*python.yml + schedule: + - cron: '17 10 * * 2' + workflow_call: + inputs: + ref: + required: true + type: string + +jobs: + analyze-python: + name: Analyze Python + runs-on: "macos-latest" + timeout-minutes: 360 + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref }} + - uses: actions/setup-python@v5 + with: + python-version: 3.x + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: python + build-mode: none + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + queries: security-extended + config: | + paths: + - bindings/python/pymongocrypt + + - name: Install package + run: | + cd bindings/python + export LIBMONGOCRYPT_VERSION=$(cat ./libmongocrypt-version.txt) + git fetch origin $LIBMONGOCRYPT_VERSION + bash release.sh + pip install dist/*.whl + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:python" diff --git a/ext/libmongocrypt/libmongocrypt/.github/workflows/dist-python.yml b/ext/libmongocrypt/libmongocrypt/.github/workflows/dist-python.yml new file mode 100644 index 0000000..8cf035e --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/.github/workflows/dist-python.yml @@ -0,0 +1,84 @@ +name: Python Dist + +on: + push: + tags: + - "pymongocrypt-[0-9]+.[0-9]+.[0-9]+" + - "pymongocrypt-[0-9]+.[0-9]+.[0-9]+.post[0-9]+" + - "pymongocrypt-[0-9]+.[0-9]+.[0-9]+[a-b][0-9]+" + - "pymongocrypt-[0-9]+.[0-9]+.[0-9]+rc[0-9]+" + pull_request: + paths: + - bindings/python/* + - bindings/python/**/*.py + - .github/workflows/*python.yml + workflow_dispatch: + workflow_call: + inputs: + force: + required: true + type: boolean + ref: + required: true + type: string + +concurrency: + group: python-dist-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + working-directory: ./bindings/python + shell: bash -eux {0} + +jobs: + build_dist: + if: github.repository_owner == 'mongodb' || inputs.force == true + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + fail-fast: false + + steps: + - name: Checkout libmongocrypt + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref }} + + - uses: actions/setup-python@v5 + with: + python-version: 3.8 + cache: 'pip' + cache-dependency-path: 'bindings/python/pyproject.toml' + allow-prereleases: true + + - name: Build and test dist files + run: | + export LIBMONGOCRYPT_VERSION=$(cat ./libmongocrypt-version.txt) + git fetch origin $LIBMONGOCRYPT_VERSION + bash ./release.sh + + - uses: actions/upload-artifact@v4 + with: + name: dist-${{ matrix.os }} + path: ./bindings/python/dist/*.* + if-no-files-found: error + + collect_dist: + runs-on: ubuntu-latest + needs: [build_dist] + name: Collect dist files + steps: + - name: Download all workflow run artifacts + uses: actions/download-artifact@v4 + - name: Flatten directory + working-directory: . + run: | + find . -mindepth 2 -type f -exec mv {} . \; + find . -type d -empty -delete + - uses: actions/upload-artifact@v4 + with: + name: all-dist-${{ github.run_id }} + path: "./*" diff --git a/ext/libmongocrypt/libmongocrypt/.github/workflows/release-python.yml b/ext/libmongocrypt/libmongocrypt/.github/workflows/release-python.yml new file mode 100644 index 0000000..5dbd3c7 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/.github/workflows/release-python.yml @@ -0,0 +1,100 @@ +name: Python Release + +on: + workflow_dispatch: + inputs: + version: + description: "The new version to set" + required: true + following_version: + description: "The post (dev) version to set" + required: true + dry_run: + description: "Dry Run?" + default: false + type: boolean + +env: + # Changes per repo + PRODUCT_NAME: PyMongoCrypt + # Changes per branch + SILK_ASSET_GROUP: pymongocrypt + EVERGREEN_PROJECT: libmongocrypt + +defaults: + run: + shell: bash -eux {0} + +jobs: + pre-publish: + environment: release-python + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + outputs: + version: ${{ steps.pre-publish.outputs.version }} + steps: + - uses: mongodb-labs/drivers-github-tools/secure-checkout@v2 + with: + app_id: ${{ vars.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: mongodb-labs/drivers-github-tools/setup@v2 + with: + aws_role_arn: ${{ secrets.AWS_ROLE_ARN }} + aws_region_name: ${{ vars.AWS_REGION_NAME }} + aws_secret_id: ${{ secrets.AWS_SECRET_ID }} + artifactory_username: ${{ vars.ARTIFACTORY_USERNAME }} + - uses: mongodb-labs/drivers-github-tools/python/pre-publish@v2 + id: pre-publish + with: + version: ${{ inputs.version }} + working_directory: ./bindings/python + dry_run: ${{ inputs.dry_run }} + tag_template: "pymongocrypt-${VERSION}" + tag_message_template: "Release PyMongoCrypt ${VERSION}" + + build-dist: + needs: [pre-publish] + uses: ./.github/workflows/dist-python.yml + with: + force: true + ref: ${{ needs.pre-publish.outputs.version }} + + static-scan: + needs: [pre-publish] + uses: ./.github/workflows/codeql.yml + with: + ref: ${{ needs.pre-publish.outputs.version }} + + publish: + needs: [build-dist, static-scan] + runs-on: ubuntu-latest + environment: release-python + permissions: + id-token: write + contents: write + attestations: write + security-events: write + steps: + - uses: mongodb-labs/drivers-github-tools/secure-checkout@v2 + with: + app_id: ${{ vars.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: mongodb-labs/drivers-github-tools/setup@v2 + with: + aws_role_arn: ${{ secrets.AWS_ROLE_ARN }} + aws_region_name: ${{ vars.AWS_REGION_NAME }} + aws_secret_id: ${{ secrets.AWS_SECRET_ID }} + artifactory_username: ${{ vars.ARTIFACTORY_USERNAME }} + - uses: mongodb-labs/drivers-github-tools/python/publish@v2 + with: + version: ${{ inputs.version }} + following_version: ${{ inputs.following_version }} + working_directory: ./bindings/python + product_name: ${{ env.PRODUCT_NAME }} + silk_asset_group: ${{ env.SILK_ASSET_GROUP }} + evergreen_project: ${{ env.EVERGREEN_PROJECT }} + tag_template: "pymongocrypt-${VERSION}" + token: ${{ github.token }} + dry_run: ${{ inputs.dry_run }} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/.github/workflows/test-python.yml b/ext/libmongocrypt/libmongocrypt/.github/workflows/test-python.yml new file mode 100644 index 0000000..23c4094 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/.github/workflows/test-python.yml @@ -0,0 +1,61 @@ +name: Python Tests + +on: + push: + pull_request: + paths: + - bindings/python/* + - bindings/python/**/*.py + - .github/workflows/*python.yml + +concurrency: + group: python-test-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + working-directory: ./bindings/python + shell: bash -eux {0} + +jobs: + + static: + if: github.repository_owner == 'mongodb' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - name: "Run pre-commit" + working-directory: . + run: | + pip install -U -q pre-commit + pre-commit run --all-files --hook-stage manual + - run: | + pip install check-manifest + check-manifest -v + + build: + if: github.repository_owner == 'mongodb' + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: ["3.8", "3.13"] + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + allow-prereleases: true + python-version: ${{ matrix.python-version }} + - name: Build and test dist files + run: | + if [ "${{ matrix.python-version }}" == "3.13" ]; then + export PIP_PRE=1 + fi + export LIBMONGOCRYPT_VERSION=$(cat ./libmongocrypt-version.txt) + git fetch origin $LIBMONGOCRYPT_VERSION + bash ./release.sh diff --git a/ext/libmongocrypt/libmongocrypt/.pre-commit-config.yaml b/ext/libmongocrypt/libmongocrypt/.pre-commit-config.yaml new file mode 100644 index 0000000..bbd2bbb --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/.pre-commit-config.yaml @@ -0,0 +1,62 @@ +files: '^bindings/python' + +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-toml + - id: check-yaml + - id: check-json + exclude: '.evergreen/atlas_data_lake/test.driverdata.json' + - id: debug-statements + - id: end-of-file-fixer + exclude: '.*\.txt' + - id: forbid-new-submodules + - id: trailing-whitespace + - id: check-executables-have-shebangs + +# We use the Python version instead of the original version which seems to require Docker +# https://github.com/koalaman/shellcheck-precommit +- repo: https://github.com/shellcheck-py/shellcheck-py + rev: v0.9.0.6 + hooks: + - id: shellcheck + name: shellcheck + args: ["--severity=error"] + +- repo: https://github.com/sirosen/check-jsonschema + rev: 0.29.0 + hooks: + - id: check-github-workflows + - id: check-github-actions + - id: check-dependabot + +- repo: https://github.com/codespell-project/codespell + rev: "v2.2.6" + hooks: + - id: codespell + exclude: | + (?x)( + .evergreen/github_app/package-lock.json| + .evergreen/csfle/bottle.py| + .pem$ + ) + args: ["-L", "fle"] + +- repo: local + hooks: + - id: executable-shell + name: executable-shell + entry: chmod +x + language: system + types: [shell] + +- repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.1.3 + hooks: + - id: ruff + args: [ "--fix", "--show-fixes" ] + - id: ruff-format diff --git a/ext/libmongocrypt/libmongocrypt/CHANGELOG.md b/ext/libmongocrypt/libmongocrypt/CHANGELOG.md index ef24763..42283e5 100644 --- a/ext/libmongocrypt/libmongocrypt/CHANGELOG.md +++ b/ext/libmongocrypt/libmongocrypt/CHANGELOG.md @@ -1,4 +1,37 @@ # ChangeLog +## 1.11.0 +### New features +- Support `range` algorithm as stable. +### Deprecated +- The Windows download URLs for [stable](https://s3.amazonaws.com/mciuploads/libmongocrypt/windows/latest_release/libmongocrypt.tar.gz) and [unstable](https://s3.amazonaws.com/mciuploads/libmongocrypt/windows/latest_release/libmongocrypt_unstable.tar.gz) are now deprecated. See the GitHub Release page for Windows downloads. +## 1.10.1 +## Fixed +- Document `range` algorithm as unstable. +## 1.10.0 +### New features +- Support KMIP `delegated` option. +- Support processing `bulkWrite` command. +- Support `range` algorithm. +## 1.9.1 +### New features +- Add Debian 12 packages +## 1.9.0 +### New features +- Support named KMS providers. +- Add `arm64` Debian packages +## Fixed +- Fix `arm64` Alpine build. +## 1.8.4 +### Fixed +- Fix `aarch64` packages for RHEL 8, RHEL 9, Amazon 2023, and Amazon 2 +## 1.8.3 +### Improvements +- Include packages for RHEL 8, RHEL 9, and Amazon 2023 +## 1.8.2 +### Fixed +- Fix possible leaks in Queryable Encryption in errors on malformed data. +## 1.8.1 +- Bypass search index management commands in automatic encryption ## 1.8.0 This release adds stable support of the Queryable Encryption (QE) feature for the "Indexed" and "Unindexed" algorithms. ## 1.8.0-alpha1 diff --git a/ext/libmongocrypt/libmongocrypt/CMakeLists.txt b/ext/libmongocrypt/libmongocrypt/CMakeLists.txt index 8dffbc4..e70cfd2 100644 --- a/ext/libmongocrypt/libmongocrypt/CMakeLists.txt +++ b/ext/libmongocrypt/libmongocrypt/CMakeLists.txt @@ -7,6 +7,10 @@ elseif (DEFINED CMAKE_MSVC_RUNTIME_LIBRARY) message (WARNING "The CMAKE_MSVC_RUNTIME_LIBRARY variable is set, but CMake is too old to understand it") endif () +if (POLICY CMP0135) + cmake_policy (SET CMP0135 NEW) +endif () + project (mongocrypt C) # Used for the csfle-markup util: @@ -20,7 +24,7 @@ option (ENABLE_PIC ON ) option (ENABLE_BUILD_FOR_PPA "Maintainer-only option for preparing PPA build" OFF) -option (ENABLE_ONLINE_TESTS "Enable online tests and the csfle utility" ON) +option (ENABLE_ONLINE_TESTS "Enable online tests and the csfle utility. Requires libmongoc." ON) if (ENABLE_WINDOWS_STATIC_RUNTIME) if (POLICY CMP0091) @@ -69,6 +73,7 @@ if (ENABLE_MORE_WARNINGS_AS_ERRORS) msvc:/W3 msvc:/WX msvc:/wd4996 msvc:/wd4359 gnu-like:-Wall gnu-like:-Werror gnu-like:-Wswitch-enum gnu-like:-Wswitch-default + gnu-like:-Wsign-compare ) add_link_options ( # Enable link-time warnings. VS 2015 sees LNK4099 spuriously, but it is a @@ -420,6 +425,9 @@ if (BUILD_TESTING) INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/src" LINK_LIBRARIES _mongocrypt::libbson_for_static COMPILE_FEATURES cxx_std_11 + # Define `__STDC_LIMIT_MACROS` in libbson to define integer macros (e.g. SIZE_MAX) when including in C++ code. + # C99 standard notes: "C++ implementations should define these macros only when __STDC_LIMIT_MACROS is defined before is included." + COMPILE_DEFINITIONS __STDC_LIMIT_MACROS PREFIX "" ) @@ -473,6 +481,7 @@ set (TEST_MONGOCRYPT_SOURCES test/test-mongocrypt-cache.c test/test-mongocrypt-cache-oauth.c test/test-mongocrypt-ciphertext.c + test/test-mongocrypt-cleanup.c test/test-mongocrypt-compact.c test/test-mongocrypt-crypto.c test/test-mongocrypt-crypto-hooks.c @@ -494,10 +503,12 @@ set (TEST_MONGOCRYPT_SOURCES test/test-mongocrypt-local-kms.c test/test-mongocrypt-log.c test/test-mongocrypt-marking.c + test/test-mongocrypt-opts.c test/test-mongocrypt-status.c test/test-mongocrypt-traverse-util.c test/test-mongocrypt-util.c test/test-mongocrypt.c + test/test-named-kms-providers.c ) # Define test-mongocrypt diff --git a/ext/libmongocrypt/libmongocrypt/CODEOWNERS b/ext/libmongocrypt/libmongocrypt/CODEOWNERS index c20dea7..00c3bc5 100644 --- a/ext/libmongocrypt/libmongocrypt/CODEOWNERS +++ b/ext/libmongocrypt/libmongocrypt/CODEOWNERS @@ -1,10 +1,7 @@ # Code Owners will automatically be added as reviewers on PRs -# NodeJS Bindings -bindings/node @nbbeeken @durran @baileympearson @dariakp @addaleax - # Python Bindings -bindings/python @ShaneHarvey @blink1073 @juliusgeo +bindings/python @mongodb/dbx-python # Java Bindings bindings/java @jyemin @rozza diff --git a/ext/libmongocrypt/libmongocrypt/Earthfile b/ext/libmongocrypt/libmongocrypt/Earthfile index 6a2b5be..ff50742 100644 --- a/ext/libmongocrypt/libmongocrypt/Earthfile +++ b/ext/libmongocrypt/libmongocrypt/Earthfile @@ -46,6 +46,7 @@ # • deb9 - Debian 9.2 # • deb10 - Debian 10.0 # • deb11 - Debian 11.0 + # • deb12 - Debian 12.0 # • sles15 - OpenSUSE Leap 15.0 # • alpine - Alpine Linux 3.18 # @@ -179,6 +180,11 @@ ENV_DEBIAN: COMMAND ARG --required version FROM +init --base=docker.io/library/debian:$version + IF [ $version = "9.2" ] + # Update source list for archived Debian stretch packages. + # Refer: https://unix.stackexchange.com/a/743865/260858 + RUN echo "deb http://archive.debian.org/debian stretch main" > /etc/apt/sources.list + END DO +DEBIAN_SETUP env.deb9: @@ -196,13 +202,17 @@ env.deb11: # A Debian 11.0 environment DO +ENV_DEBIAN --version 11.0 +env.deb12: + # A Debian 12.0 environment + DO +ENV_DEBIAN --version 12.0 + env.sles15: # An OpenSUSE Leap 15.0 environment. FROM +init --base=docker.io/opensuse/leap:15.0 DO +SLES_SETUP env.alpine: - FROM +init --base=docker.io/library/alpine:3.17 + FROM +init --base=docker.io/library/alpine:3.18 DO +ALPINE_SETUP # Utility: Warm-up obtaining CMake and Ninja for the build. This is usually @@ -249,7 +259,7 @@ BUILD_EXAMPLE_STATE_MACHINE: RUN cd /s && /s/example-state-machine rpm-build: - FROM +init --base fedora:rawhide + FROM +init --base fedora:38 GIT CLONE https://src.fedoraproject.org/rpms/libmongocrypt.git /R # Install the packages listed by "BuildRequires" and rpm-build: RUN __install $(awk '/^BuildRequires:/ { print $2 }' /R/libmongocrypt.spec) \ @@ -265,7 +275,7 @@ rpm-build: rpm-install-runtime: # Install the runtime RPM - FROM +init --base fedora:rawhide + FROM +init --base fedora:38 COPY +rpm-build/RPMS /tmp/libmongocrypt-rpm/ RUN dnf makecache RUN __install $(find /tmp/libmongocrypt-rpm/ -name 'libmongocrypt-1.*.rpm') @@ -372,3 +382,141 @@ build: CACHE /s/libmongocrypt/cmake-build END RUN env USE_NINJA=1 bash libmongocrypt/.evergreen/build_all.sh + SAVE ARTIFACT /s/install /libmongocrypt-install + +# `create-deb-packages-and-repos` creates the .deb packages and repo directories intended for the PPA on debian-like distros. Options: +# • --env=[...] +# · Set the environment for the build. Only debian-like environments are supported. +# • --packager_distro=[...] is passed to `create-packages-and-repos.sh` +# • --packager_arch=[...] is passed to `create-packages-and-repos.sh` +create-deb-packages-and-repos: + ARG env + FROM +env.$env + DO +CACHE_WARMUP + DO +COPY_SOURCE + WORKDIR /s + RUN __install dh-make dpkg-dev apt-utils + ARG packager_distro + ARG packager_arch + RUN env \ + WORKDIR=/s \ + PYTHON=python3 \ + HAS_PACKAGES=true \ + PACKAGER_DISTRO=$packager_distro \ + PACKAGER_ARCH=$packager_arch \ + bash libmongocrypt/.evergreen/create-packages-and-repos.sh + SAVE ARTIFACT libmongocrypt/repo AS LOCAL repo + +# `test-deb-packages-from-ppa` tests Debian and Ubuntu packages installed on the PPA. +# • --env=[...] (default "deb11") +# · Set the environment for the build. Only debian-like environments are supported. +# • --distro=[...] (default "debian bullseye") +# · Has the form: "(debian|ubuntu) (name)". Must match distro set for `--env`. +# • --version=[...] (default "development"). The libmongocrypt package version. +# · May refer to a release branch (e.g. "1.8"). Release branch packages are updated on a tagged release. +# · "development" packages are updated by the `publish-packages` tasks every commit. +test-deb-packages-from-ppa: + ARG env="deb11" + ARG distro="debian bullseye" + ARG version="development" + FROM +env.$env + WORKDIR /s + RUN __install apt-transport-https + # Install libmongocrypt following install steps described in README.md: + RUN curl -s --location https://pgp.mongodb.com/libmongocrypt.asc | gpg --dearmor >/etc/apt/trusted.gpg.d/libmongocrypt.gpg + RUN echo "deb https://libmongocrypt.s3.amazonaws.com/apt/$distro/libmongocrypt/$version main" | tee /etc/apt/sources.list.d/libmongocrypt.list + # Test using libmongocrypt: + RUN __install libmongocrypt-dev gcc + RUN echo " + #include + #include + int main(void) { + const char *ver = mongocrypt_version(NULL); + printf (\"Using libmongocrypt %s\", ver); + }" > test.c + RUN gcc -o test.out test.c $(pkg-config --libs --cflags libmongocrypt) + RUN ./test.out + +# `sign` uses Garasign to sign a file with the libmongocrypt key. +# Requires prior authentication with Artifactory. +# See: https://docs.devprod.prod.corp.mongodb.com/release-tools-container-images/garasign/garasign_signing/. +sign: + ARG --required file_to_sign + ARG --required output_file + FROM artifactory.corp.mongodb.com/release-tools-container-registry-local/garasign-gpg + WORKDIR /s + COPY ${file_to_sign} /s/file + RUN --secret garasign_username --secret garasign_password \ + GRS_CONFIG_USER1_USERNAME=${garasign_username} \ + GRS_CONFIG_USER1_PASSWORD=${garasign_password} \ + /bin/bash -c "gpgloader && gpg --yes -v --armor -o /s/file.asc --detach-sign /s/file" + # Verify the signature + RUN touch /keyring + RUN curl -sS https://pgp.mongodb.com/libmongocrypt.pub | gpg -q --no-default-keyring --keyring "/keyring" --import - + RUN gpgv --keyring "/keyring" "/s/file.asc" "/s/file" + SAVE ARTIFACT /s/file.asc AS LOCAL ${output_file} + +# silkbomb: +# An environment with the `silkbomb` command. +# +# See https://docs.devprod.prod.corp.mongodb.com/mms/python/src/sbom/silkbomb/ for documentation of silkbomb. +silkbomb: + FROM artifactory.corp.mongodb.com/release-tools-container-registry-public-local/silkbomb:1.0 + # Alias the silkbom executable to a simpler name: + RUN ln -s /python/src/sbom/silkbomb/bin /usr/local/bin/silkbomb + +# sbom-generate: +# Generate/update the etc/cyclonedx.sbom.json file from the etc/purls.txt file. +# +# This target will update the existing etc/cyclonedx.sbom.json file in-place based +# on the content of etc/purls.txt. +# +sbom-generate: + FROM +silkbomb + # Copy in the relevant files: + WORKDIR /s + COPY etc/purls.txt etc/cyclonedx.sbom.json /s/ + # Update the SBOM file: + RUN silkbomb update \ + --purls purls.txt \ + --sbom-in cyclonedx.sbom.json \ + --sbom-out cyclonedx.sbom.json + # Save the result back to the host: + SAVE ARTIFACT /s/cyclonedx.sbom.json AS LOCAL etc/cyclonedx.sbom.json + +# sbom-download: +# Download the Augmented SBOM file from Silk. +# +# See https://wiki.corp.mongodb.com/display/DRIVERS/Using+AWS+Secrets+Manager+to+Store+Testing+Secrets for instructions to get secrets from AWS Secrets Manager. Secrets are available under `drivers/libmongocrypt`. +# +sbom-download: + ARG --required out + ARG --required branch + FROM +silkbomb + WORKDIR /s + # Download the Augmented SBOM file: + RUN --no-cache --secret silk_client_id --secret silk_client_secret \ + SILK_CLIENT_ID=${silk_client_id} \ + SILK_CLIENT_SECRET=${silk_client_secret} \ + silkbomb download \ + --sbom-out cyclonedx.augmented.sbom.json \ + --silk-asset-group libmongocrypt-${branch} + # Save the result back to the host: + SAVE ARTIFACT /s/cyclonedx.augmented.sbom.json AS LOCAL ${out} + RUN echo "Augmented SBOM saved to ${out}" + +# silk-create-asset-group: +# Create an asset group for Silk. +# +# See https://wiki.corp.mongodb.com/display/DRIVERS/Using+AWS+Secrets+Manager+to+Store+Testing+Secrets for instructions to get secrets from AWS Secrets Manager. Secrets are available under `drivers/libmongocrypt`. +# +silk-create-asset-group: + ARG --required branch + FROM +env.alpine + RUN __install curl jq + COPY etc/silk-create-asset-group.sh /s/silk-create-asset-group.sh + RUN --no-cache --secret silk_client_id --secret silk_client_secret \ + silk_client_id=${silk_client_id} \ + silk_client_secret=${silk_client_secret} \ + branch=${branch} \ + /s/silk-create-asset-group.sh diff --git a/ext/libmongocrypt/libmongocrypt/README.md b/ext/libmongocrypt/libmongocrypt/README.md index 77be74d..a62f9bb 100644 --- a/ext/libmongocrypt/libmongocrypt/README.md +++ b/ext/libmongocrypt/libmongocrypt/README.md @@ -72,12 +72,10 @@ find_package (mongocrypt) ``` ## Installing libmongocrypt on Windows ## -For Windows, there is a fixed URL to download the DLL and includes directory: -https://s3.amazonaws.com/mciuploads/libmongocrypt/windows/latest_release/libmongocrypt.tar.gz +A Windows DLL for x86_64 is available on the Github Releases page. See the [latest release](https://github.com/mongodb/libmongocrypt/releases/latest). + +Use `gpg` to verify the signature. The public key for `libmongocrypt` is available on https://pgp.mongodb.com/. -To download the latest unstable release, download from this URL: -https://s3.amazonaws.com/mciuploads/libmongocrypt/windows/latest_release/libmongocrypt_unstable.tar.gz -Do not use the unstable version of libmongocrypt in a production environment. ### Testing ### `test-mongocrypt` mocks all I/O with files stored in the `test/data` and `test/example` directories. Run `test-mongocrypt` from the source directory: @@ -108,53 +106,32 @@ We decided against the "have libmongocrypt do everything" approach because it co ### Releasing ### -#### Version number scheme #### -Version numbers of libmongocrypt must follow the format 1.[0-9].[0-9] for releases and 1.[0-9].[0-9]-(alpha|beta|rc)[0-9] for pre-releases. This ensures that Linux distribution packages built from each commit are published to the correct location. - -#### Steps to release #### -Do the following when releasing: -- Update CHANGELOG.md with the version being released. -- If this is a new minor release (e.g. `x.y.0`): - - Update the Linux distribution package installation instructions in the below sections to refer to the new version x.y. - - Commit these changes (on `master`) so that both the `master` branch and the new branch you are about to create refer to the new branch (note that this means you will commit changes to this file, and `CHANGELOG.md`) - - Create a branch named `rx.y`. - - Update the [libmongocrypt-release](https://evergreen.mongodb.com/projects##libmongocrypt-release) Evergreen project (requires auth) to set `Branch Name` to `rx.y`. -- Commit, create a new git tag, like `1.0.0-rc123` or `1.0.0`, and push. - - Push both the branch ref and tag ref in the same command: `git push origin master 1.0.0-rc123` or `git push origin r1.0 1.0.0` - - Pushing the branch ref and the tag ref in the same command eliminates the possibility of a race condition in Evergreen (for building resources based on the presence of a release tag) - - Note that in the future (e.g., if we move to a PR-based workflow for releases, or if we simply want to take better advantage of advanced Evergreen features), it is possible to use Evergreen's "Trigger Versions With Git Tags" feature by updating both `config.yml` and the project's settings in Evergreen -- Ensure the version on Evergreen with the tagged commit is scheduled. The following tasks must pass to complete the release: - - `upload-all` - - `windows-upload`. It is scheduled from the `windows-upload-check` task. -- Create the release from the GitHub releases page from the new tag. -- Submit a PR to update the Homebrew package https://github.com/mongodb/homebrew-brew/blob/master/Formula/libmongocrypt.rb. ([Example](https://github.com/mongodb/homebrew-brew/pull/135)). -- If this is a new minor release (e.g. `x.y.0`), file a DOCSP ticket to update the installation instructions on [Install libmongocrypt](https://www.mongodb.com/docs/manual/core/csfle/reference/libmongocrypt/). ([Example](https://jira.mongodb.org/browse/DOCSP-26877)) -- Update the release on the [Jira releases page](https://jira.mongodb.org/projects/MONGOCRYPT/versions). +See [releasing](./doc/releasing.md). ## Installing libmongocrypt From Distribution Packages ## Distribution packages (i.e., .deb/.rpm) are built and published for several Linux distributions. The installation of these packages for supported platforms is documented here. ### Unstable Development Distribution Packages ### -To install the latest unstable development package, change `1.8` to `development` in the package URLs listed in the subsequent instructions. For example, `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.8` in the instructions would become `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/development`. Do not use the unstable version of libmongocrypt in a production environment. +To install the latest unstable development package, change `1.11` to `development` in the package URLs listed in the subsequent instructions. For example, `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.11` in the instructions would become `https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/development`. Do not use the unstable version of libmongocrypt in a production environment. ### .deb Packages (Debian and Ubuntu) ### First, import the public key used to sign the package repositories: ``` -sudo sh -c 'curl -s --location https://www.mongodb.org/static/pgp/libmongocrypt.asc | gpg --dearmor >/etc/apt/trusted.gpg.d/libmongocrypt.gpg' +sudo sh -c 'curl -s --location https://pgp.mongodb.com/libmongocrypt.asc | gpg --dearmor >/etc/apt/trusted.gpg.d/libmongocrypt.gpg' ``` Second, create a list entry for the repository. For Ubuntu systems (be sure to change `` to `xenial`, `bionic`, `focal`, or `jammy`, as appropriate to your system): ``` -echo "deb https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.8 universe" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list +echo "deb https://libmongocrypt.s3.amazonaws.com/apt/ubuntu /libmongocrypt/1.11 universe" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list ``` -For Debian systems (be sure to change `` to `stretch`, `buster`, or `bullseye`, as appropriate to your system): +For Debian systems (be sure to change `` to `stretch`, `buster`, `bullseye`, or `bookworm` as appropriate to your system): ``` -echo "deb https://libmongocrypt.s3.amazonaws.com/apt/debian /libmongocrypt/1.8 main" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list +echo "deb https://libmongocrypt.s3.amazonaws.com/apt/debian /libmongocrypt/1.11 main" | sudo tee /etc/apt/sources.list.d/libmongocrypt.list ``` Third, update the package cache: @@ -179,10 +156,29 @@ Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository -baseurl=https://libmongocrypt.s3.amazonaws.com/yum/redhat/$releasever/libmongocrypt/1.8/x86_64 +baseurl=https://libmongocrypt.s3.amazonaws.com/yum/redhat/$releasever/libmongocrypt/1.11/x86_64 +gpgcheck=1 +enabled=1 +gpgkey=https://pgp.mongodb.com/libmongocrypt.asc +``` + +Then install the libmongocrypt packages: + +``` +sudo yum install -y libmongocrypt +``` + +#### Amazon Linux 2023 #### + +Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: + +``` +[libmongocrypt] +name=libmongocrypt repository +baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2023/libmongocrypt/1.11/x86_64 gpgcheck=1 enabled=1 -gpgkey=https://www.mongodb.org/static/pgp/libmongocrypt.asc +gpgkey=https://pgp.mongodb.com/libmongocrypt.asc ``` Then install the libmongocrypt packages: @@ -198,10 +194,10 @@ Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository -baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2/libmongocrypt/1.8/x86_64 +baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2/libmongocrypt/1.11/x86_64 gpgcheck=1 enabled=1 -gpgkey=https://www.mongodb.org/static/pgp/libmongocrypt.asc +gpgkey=https://pgp.mongodb.com/libmongocrypt.asc ``` Then install the libmongocrypt packages: @@ -217,10 +213,10 @@ Create the file `/etc/yum.repos.d/libmongocrypt.repo` with contents: ``` [libmongocrypt] name=libmongocrypt repository -baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2013.03/libmongocrypt/1.8/x86_64 +baseurl=https://libmongocrypt.s3.amazonaws.com/yum/amazon/2013.03/libmongocrypt/1.11/x86_64 gpgcheck=1 enabled=1 -gpgkey=https://www.mongodb.org/static/pgp/libmongocrypt.asc +gpgkey=https://pgp.mongodb.com/libmongocrypt.asc ``` Then install the libmongocrypt packages: @@ -234,13 +230,13 @@ sudo yum install -y libmongocrypt First, import the public key used to sign the package repositories: ``` -sudo rpm --import https://www.mongodb.org/static/pgp/libmongocrypt.asc +sudo rpm --import https://pgp.mongodb.com/libmongocrypt.asc ``` Second, add the repository (be sure to change `` to `12` or `15`, as appropriate to your system): ``` -sudo zypper addrepo --gpgcheck "https://libmongocrypt.s3.amazonaws.com/zypper/suse//libmongocrypt/1.8/x86_64" libmongocrypt +sudo zypper addrepo --gpgcheck "https://libmongocrypt.s3.amazonaws.com/zypper/suse//libmongocrypt/1.11/x86_64" libmongocrypt ``` Finally, install the libmongocrypt packages: diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/CMakeLists.txt b/ext/libmongocrypt/libmongocrypt/bindings/cs/CMakeLists.txt index bd709d7..f55cc07 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/CMakeLists.txt +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/CMakeLists.txt @@ -1,5 +1,6 @@ configure_file(cs.sln cs.sln COPYONLY) +configure_file(MongoDB.Driver.snk MongoDB.Driver.snk COPYONLY) configure_file(MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj COPYONLY) configure_file(MongoDB.Libmongocrypt/Package.include.template.csproj MongoDB.Libmongocrypt/Package.csproj.include) diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Driver.snk b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Driver.snk new file mode 100644 index 0000000..f8eaad4 Binary files /dev/null and b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Driver.snk differ diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj index c510105..7678ad0 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/MongoDB.Libmongocrypt.Test.csproj @@ -6,6 +6,8 @@ AnyCPU false + true + ..\MongoDB.Driver.snk diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj index f13794d..5f5cb2d 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test32/MongoDB.Libmongocrypt.Test32.csproj @@ -4,6 +4,8 @@ net472;netcoreapp2.1;netcoreapp3.0 netcoreapp2.1;netcoreapp3.0 false + true + ..\MongoDB.Driver.snk diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/AssemblyInfo.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/AssemblyInfo.cs index 7b0f531..0d7b58a 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/AssemblyInfo.cs +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/AssemblyInfo.cs @@ -1,4 +1,4 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("MongoDB.Libmongocrypt.Test")] -[assembly: InternalsVisibleTo("MongoDB.Libmongocrypt.Test32")] +[assembly: InternalsVisibleTo("MongoDB.Libmongocrypt.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010035287f0d3883c0a075c88e0cda3ce93b621003ecbd5e920d4a8c7238564f4d2f4f68116aca28c9b21341dc3a877679c14556192b2b2f5fe2c11d624e0894d308ff7b94bf6fd72aef1b41017ffe2572e99019d1c61963e68cd0ed67734a42cb333b808e3867cbe631937214e32e409fb1fa62fdb69d494c2530e64a40e417d6ee")] +[assembly: InternalsVisibleTo("MongoDB.Libmongocrypt.Test32, PublicKey=002400000480000094000000060200000024000052534131000400000100010035287f0d3883c0a075c88e0cda3ce93b621003ecbd5e920d4a8c7238564f4d2f4f68116aca28c9b21341dc3a877679c14556192b2b2f5fe2c11d624e0894d308ff7b94bf6fd72aef1b41017ffe2572e99019d1c61963e68cd0ed67734a42cb333b808e3867cbe631937214e32e409fb1fa62fdb69d494c2530e64a40e417d6ee")] diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Binary.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Binary.cs index b7f9bd4..3fd3714 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Binary.cs +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Binary.cs @@ -48,7 +48,14 @@ internal Binary(BinarySafeHandle handle) /// public IntPtr Data { - get { return Library.mongocrypt_binary_data(_handle); } + get + { + if (!_handle.IsInvalid) + { + return Marshal.ReadIntPtr(_handle.DangerousGetHandle()); + } + return IntPtr.Zero; + } } /// @@ -59,7 +66,14 @@ public IntPtr Data /// public uint Length { - get { return Library.mongocrypt_binary_len(_handle); } + get + { + if (!_handle.IsInvalid) + { + return (uint)Marshal.ReadInt32(_handle.DangerousGetHandle(), IntPtr.Size); + } + return 0; + } } internal BinarySafeHandle Handle => _handle; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClientFactory.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClientFactory.cs index 46d2495..fb2ebb9 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClientFactory.cs +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClientFactory.cs @@ -15,6 +15,7 @@ */ using System; +using System.Linq; namespace MongoDB.Libmongocrypt { @@ -34,6 +35,9 @@ public class CryptClientFactory private static Library.Delegates.RandomCallback __randomCallback = new Library.Delegates.RandomCallback(SecureRandomCallback.GenerateRandom); private static Library.Delegates.CryptoHmacCallback __signRsaesPkcs1HmacCallback = new Library.Delegates.CryptoHmacCallback(SigningRSAESPKCSCallback.RsaSign); + // mongocrypt_is_crypto_available is only available in libmongocrypt version >= 1.9 + private static readonly Version __mongocryptIsCryptoAvailableMinVersion = Version.Parse("1.9"); + /// Creates a CryptClient with the specified options. /// The options. /// A CryptClient @@ -42,14 +46,14 @@ public static CryptClient Create(CryptOptions options) MongoCryptSafeHandle handle = null; Status status = null; + var cryptoAvailable = Version.Parse(Library.Version.Split('-', '+').First()) >= __mongocryptIsCryptoAvailableMinVersion && Library.mongocrypt_is_crypto_available(); + try { handle = Library.mongocrypt_new(); status = new Status(); - - // The below code can be avoided on Windows. So, we don't call it on this system - // to avoid restrictions on target frameworks that present in some of below - if (OperatingSystemHelper.CurrentOperatingSystem != OperatingSystemPlatform.Windows) + + if (!cryptoAvailable) { handle.Check( status, diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Library.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Library.cs index b77035c..13d1bab 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Library.cs +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Library.cs @@ -48,6 +48,9 @@ static Library() _mongocrypt_ctx_setopt_key_encryption_key = new Lazy( () => __loader.Value.GetFunction( ("mongocrypt_ctx_setopt_key_encryption_key")), true); + + _mongocrypt_is_crypto_available = new Lazy( + () => __loader.Value.GetFunction("mongocrypt_is_crypto_available"), true); _mongocrypt_setopt_aes_256_ecb = new Lazy( () => __loader.Value.GetFunction( @@ -229,6 +232,8 @@ public static string Version internal static Delegates.mongocrypt_setopt_log_handler mongocrypt_setopt_log_handler => _mongocrypt_setopt_log_handler.Value; internal static Delegates.mongocrypt_setopt_kms_providers mongocrypt_setopt_kms_providers => _mongocrypt_setopt_kms_providers.Value; internal static Delegates.mongocrypt_ctx_setopt_key_encryption_key mongocrypt_ctx_setopt_key_encryption_key => _mongocrypt_ctx_setopt_key_encryption_key.Value; + + internal static Delegates.mongocrypt_is_crypto_available mongocrypt_is_crypto_available => _mongocrypt_is_crypto_available.Value; internal static Delegates.mongocrypt_setopt_aes_256_ecb mongocrypt_setopt_aes_256_ecb => _mongocrypt_setopt_aes_256_ecb.Value; internal static Delegates.mongocrypt_setopt_bypass_query_analysis mongocrypt_setopt_bypass_query_analysis => _mongocrypt_setopt_bypass_query_analysis.Value; @@ -306,6 +311,8 @@ public static string Version private static readonly Lazy _mongocrypt_setopt_kms_providers; private static readonly Lazy _mongocrypt_ctx_setopt_key_encryption_key; + + private static readonly Lazy _mongocrypt_is_crypto_available; private static readonly Lazy _mongocrypt_setopt_aes_256_ecb; private static readonly Lazy _mongocrypt_setopt_bypass_query_analysis; @@ -399,6 +406,9 @@ internal class Delegates public delegate MongoCryptSafeHandle mongocrypt_new(); + [return: MarshalAs(UnmanagedType.I1)] + public delegate bool mongocrypt_is_crypto_available(); + public delegate void LogCallback([MarshalAs(UnmanagedType.I4)] LogLevel level, IntPtr messasge, uint message_length, IntPtr context); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoader.cs b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoader.cs index 5390e2a..cccb36a 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoader.cs +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/LibraryLoader.cs @@ -28,6 +28,7 @@ namespace MongoDB.Libmongocrypt internal class LibraryLoader { private ISharedLibraryLoader _loader; + private static readonly string __libmongocryptLibPath = Environment.GetEnvironmentVariable("LIBMONGOCRYPT_PATH"); public LibraryLoader() { @@ -54,40 +55,13 @@ public LibraryLoader() switch (OperatingSystemHelper.CurrentOperatingSystem) { case OperatingSystemPlatform.MacOS: - { - string[] suffixPaths = new[] - { - "../../runtimes/osx/native/", - "runtimes/osx/native/", - string.Empty - }; - string path = FindLibrary(candidatePaths, suffixPaths, "libmongocrypt.dylib"); - _loader = new DarwinLibraryLoader(path); - } + _loader = new DarwinLibraryLoader(candidatePaths); break; case OperatingSystemPlatform.Linux: - { - string[] suffixPaths = new[] - { - "../../runtimes/linux/native/", - "runtimes/linux/native/", - string.Empty - }; - string path = FindLibrary(candidatePaths, suffixPaths, "libmongocrypt.so"); - _loader = new LinuxLibrary(path); - } + _loader = new LinuxLibrary(candidatePaths); break; case OperatingSystemPlatform.Windows: - { - string[] suffixPaths = new[] - { - @"..\..\runtimes\win\native\", - @".\runtimes\win\native\", - string.Empty - }; - string path = FindLibrary(candidatePaths, suffixPaths, "mongocrypt.dll"); - _loader = new WindowsLibrary(path); - } + _loader = new WindowsLibrary(candidatePaths); break; default: // should not be reached. If we're here, then there is a bug in OperatingSystemHelper @@ -95,7 +69,7 @@ public LibraryLoader() } } - private string FindLibrary(IList basePaths, string[] suffixPaths, string library) + private static string FindLibrary(IList basePaths, string[] suffixPaths, string library) { var candidates = new List(); foreach (var basePath in basePaths) @@ -150,9 +124,17 @@ private class DarwinLibraryLoader : ISharedLibraryLoader public const int RTLD_GLOBAL = 0x8; public const int RTLD_NOW = 0x2; + private static readonly string[] __suffixPaths = + { + "../../runtimes/osx/native/", + "runtimes/osx/native/", + string.Empty + }; + private readonly IntPtr _handle; - public DarwinLibraryLoader(string path) + public DarwinLibraryLoader(List candidatePaths) { + var path = __libmongocryptLibPath ?? FindLibrary(candidatePaths, __suffixPaths, "libmongocrypt.dylib"); _handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW); if (_handle == IntPtr.Zero) { @@ -186,11 +168,37 @@ private class LinuxLibrary : ISharedLibraryLoader // #define RTLD_GLOBAL 0x100 public const int RTLD_GLOBAL = 0x100; public const int RTLD_NOW = 0x2; + private static readonly bool _use_libdl1; + + static LinuxLibrary() + { + try + { + Libdl1.dlerror(); + _use_libdl1 = true; + } + catch + { + _use_libdl1 = false; + } + } + + private static readonly string[] __suffixPaths = + { + "../../runtimes/linux/native/", + "runtimes/linux/native/", + string.Empty + }; private readonly IntPtr _handle; - public LinuxLibrary(string path) + public LinuxLibrary(List candidatePaths) { - _handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW); + var path = __libmongocryptLibPath ?? FindLibrary(candidatePaths, __suffixPaths, "libmongocrypt.so"); + + _handle = _use_libdl1 + ? Libdl1.dlopen(path, RTLD_GLOBAL | RTLD_NOW) + : Libdl2.dlopen(path, RTLD_GLOBAL | RTLD_NOW); + if (_handle == IntPtr.Zero) { throw new FileNotFoundException(path); @@ -199,16 +207,8 @@ public LinuxLibrary(string path) public IntPtr GetFunction(string name) { - return dlsym(_handle, name); + return _use_libdl1 ? Libdl1.dlsym(_handle, name) : Libdl2.dlsym(_handle, name); } - -#pragma warning disable IDE1006 // Naming Styles - [DllImport("libdl")] - public static extern IntPtr dlopen(string filename, int flags); - - [DllImport("libdl", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr dlsym(IntPtr handle, string symbol); -#pragma warning restore IDE1006 // Naming Styles } /// @@ -216,9 +216,17 @@ public IntPtr GetFunction(string name) /// private class WindowsLibrary : ISharedLibraryLoader { + private static readonly string[] __suffixPaths = + { + @"..\..\runtimes\win\native\", + @".\runtimes\win\native\", + string.Empty + }; + private readonly IntPtr _handle; - public WindowsLibrary(string path) + public WindowsLibrary(List candidatePaths) { + var path = __libmongocryptLibPath ?? FindLibrary(candidatePaths, __suffixPaths, "mongocrypt.dll"); _handle = LoadLibrary(path); if (_handle == IntPtr.Zero) { @@ -248,5 +256,34 @@ public IntPtr GetFunction(string name) [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); } + + private static class Libdl1 + { + private const string LibName = "libdl"; + +#pragma warning disable IDE1006 // Naming Styles + [DllImport(LibName)] + public static extern IntPtr dlopen(string filename, int flags); + + [DllImport(LibName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr dlsym(IntPtr handle, string symbol); + + [DllImport(LibName)] + public static extern string dlerror(); +#pragma warning restore IDE1006 // Naming Styles + } + + private static class Libdl2 + { + private const string LibName = "libdl.so.2"; + +#pragma warning disable IDE1006 // Naming Styles + [DllImport(LibName)] + public static extern IntPtr dlopen(string filename, int flags); + + [DllImport(LibName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr dlsym(IntPtr handle, string symbol); +#pragma warning restore IDE1006 // Naming Styles + } } } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj index ba684de..049f45e 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/MongoDB.Libmongocrypt.csproj @@ -24,11 +24,12 @@ mongodb;mongo;nosql en-US true + true + ..\MongoDB.Driver.snk ../../../cmake-build/$(Configuration) - ../../../cmake-build/RelWithDebInfo/ diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/README.md b/ext/libmongocrypt/libmongocrypt/bindings/cs/README.md index 0098e2c..2469dc1 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/README.md +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/README.md @@ -54,6 +54,9 @@ If you see `Windows Error: 126` during tests, like the example below, it means t 2. cd /bindings/cs 3. dotnet build cs.build ``` +*Note*: You can use the ```LIBMONGOCRYPT_PATH``` environment variable to load a locally installed +libmongocrypt build. You should specify the absolute path to the libmongocrypt library itself, not just the containing folder. For example on Linux: +```$ export LIBMONGOCRYPT_PATH='/path/to/libmongocrypt.so'```. # Testing Do not modify xunit.runner.json diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.cake b/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.cake index 1456189..84adfcf 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.cake +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.cake @@ -1,7 +1,7 @@ -#addin nuget:?package=Cake.FileHelpers&version=3.3.0 -#addin nuget:?package=Cake.Git&version=0.22.0 -#addin nuget:?package=Cake.Incubator&version=5.1.0 -#tool dotnet:?package=GitVersion.Tool&version=5.3.7 +#addin nuget:?package=Cake.FileHelpers&version=5.0.0 +#addin nuget:?package=Cake.Git&version=2.0.0 +#addin nuget:?package=Cake.Incubator&version=7.0.0 +#tool dotnet:?package=GitVersion.Tool&version=5.10.3 using System; using System.Linq; @@ -14,15 +14,17 @@ var gitVersion = GitVersion(); var buildDirectory = MakeAbsolute(Directory(GetSettingValue("buildDirectory", "c:\\build"))); var libmongocryptAllDirectory=buildDirectory.Combine("libmongocrypt-all"); var downloadedMongocryptDirectory=buildDirectory.Combine("downloadedMongocryptDirectory"); -var localReleaseVersion = "local-0.0.0"; +var localReleaseVersion = "0.0.0-local"; var releaseVersion = GetSettingValue("releaseVersion", localReleaseVersion); -var fork = GetSettingValue("fork", "https://github.com/mongodb/libmongocrypt.git"); +var fork = GetSettingValue("fork", "git@github.com:mongodb/libmongocrypt.git"); var branch = GetSettingValue("branch", "master"); -// 1.8.0-alpha0 -var libmongocryptAllUrl = GetSettingValue("url", "https://mciuploads.s3.amazonaws.com/libmongocrypt/all/1.8.0-alpha0/libmongocrypt-all.tar.gz"); + +// 1.10.0 - latest libmongocrypt release +var libmongocryptAllUrl = GetSettingValue("url", "https://mciuploads.s3.amazonaws.com/libmongocrypt/all/1.10.0/libmongocrypt-all.tar.gz"); + var csharpBindingsGitTagName = $"csharp-v{releaseVersion}"; var csharpBindingsDirectory = buildDirectory.Combine(csharpBindingsGitTagName); -var libmongocryptRelWithDebInfoDirectory = csharpBindingsDirectory.Combine("cmake-build").Combine("RelWithDebInfo"); +var libmongocryptRelWithDebInfoDirectory = csharpBindingsDirectory.Combine("cmake-build").Combine($"{configuration}"); var libmongocryptCsDirectory = csharpBindingsDirectory.Combine("bindings").Combine("cs"); var libmongocryptSolutionDirectory = libmongocryptCsDirectory.Combine("MongoDB.Libmongocrypt"); var libmongocryptSolutionFile = libmongocryptSolutionDirectory.CombineWithFilePath("MongoDB.Libmongocrypt.csproj"); @@ -57,16 +59,9 @@ Task("Prepare") UncompressToTheCurrentDirectory(nativeLibrariesArchive); Information("Cloning the libmongocrypt repo.."); - GitClone( - fork, - csharpBindingsDirectory, - new GitCloneSettings - { - BranchName = branch, - Checkout = true, - IsBare = false, - RecurseSubmodules = true - }); + EnsureDirectoryExists(csharpBindingsDirectory); + Git(csharpBindingsDirectory, $"clone {fork} -b {branch} ."); + Information("Done git clone.."); EnsureDirectoryExists(libmongocryptRelWithDebInfoDirectory); EnsureDirectoryExists(downloadedMongocryptDirectory); @@ -77,7 +72,7 @@ Task("Prepare") libmongocryptAllDirectory.Combine("ubuntu1804-64").Combine("nocrypto").Combine("lib").CombineWithFilePath("libmongocrypt.so"), downloadedMongocryptDirectory.CombineWithFilePath("libmongocrypt.so")); CopyFile( - libmongocryptAllDirectory.Combine("macos").Combine("nocrypto").Combine("lib").CombineWithFilePath("libmongocrypt.dylib"), + libmongocryptAllDirectory.Combine("macos").Combine("lib").CombineWithFilePath("libmongocrypt.dylib"), downloadedMongocryptDirectory.CombineWithFilePath("libmongocrypt.dylib")); CopyDirectory(downloadedMongocryptDirectory, libmongocryptRelWithDebInfoDirectory); }); @@ -99,7 +94,7 @@ Task("Tests") (monikerInfo) => { Information($"Test running {monikerInfo.Moniker}.."); - var settings = new DotNetCoreTestSettings + var settings = new DotNetTestSettings { Configuration = configuration, Framework = monikerInfo.Moniker, @@ -107,7 +102,7 @@ Task("Tests") }; var projectFullPath = libmongocryptTestsSolutionDirectory.CombineWithFilePath("MongoDB.Libmongocrypt.Test.csproj").FullPath; Information(projectFullPath); - DotNetCoreTest( + DotNetTest( projectFullPath, settings ); @@ -120,7 +115,7 @@ Task("CreatePackage") { var projectFullPath = libmongocryptSolutionFile.FullPath; Information($"Project path: {projectFullPath}. ReleaseVersion: {releaseVersion}"); - var settings = new DotNetCorePackSettings + var settings = new DotNetPackSettings { Configuration = configuration, OutputDirectory = artifactsDirectory, @@ -129,7 +124,7 @@ Task("CreatePackage") { "Version", releaseVersion }, } }; - DotNetCorePack( + DotNetPack( projectFullPath, settings); }); @@ -142,9 +137,9 @@ Task("NugetPush") var nugetApi = GetSettingValue("NugetApiKey", null); var packageFilePath = artifactsDirectory.CombineWithFilePath($"{libmongocryptSolutionFile.GetFilenameWithoutExtension().ToString()}.{releaseVersion}.nupkg"); Information(packageFilePath); - NuGetPush( + DotNetNuGetPush( packageFilePath, - new NuGetPushSettings + new DotNetNuGetPushSettings { ApiKey = nugetApi, Source = "https://api.nuget.org/v3/index.json" diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.config b/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.config new file mode 100644 index 0000000..6600eee --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.config @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +CAKE_VERSION=2.2.0 +DOTNET_VERSION=6.0.400 \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.sh b/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.sh old mode 100644 new mode 100755 diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.evergreen/publish.sh b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.evergreen/publish.sh index b377faf..61945f3 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.evergreen/publish.sh +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.evergreen/publish.sh @@ -8,18 +8,18 @@ set -o errexit # Exit the script with error if any of the commands fail # Main Program # ############################################ -echo ${RING_FILE_GPG_BASE64} | base64 -d > ${PROJECT_DIRECTORY}/secring.gpg +echo ${ring_file_gpg_base64} | base64 -d > ${PROJECT_DIRECTORY}/secring.gpg trap "rm ${PROJECT_DIRECTORY}/secring.gpg; exit" EXIT HUP -export ORG_GRADLE_PROJECT_nexusUsername=${NEXUS_USERNAME} -export ORG_GRADLE_PROJECT_nexusPassword=${NEXUS_PASSWORD} -export ORG_GRADLE_PROJECT_signing_keyId=${SIGNING_KEY_ID} -export ORG_GRADLE_PROJECT_signing_password=${SIGNING_PASSWORD} +export ORG_GRADLE_PROJECT_nexusUsername=${nexus_username} +export ORG_GRADLE_PROJECT_nexusPassword=${nexus_password} +export ORG_GRADLE_PROJECT_signing_keyId=${signing_keyId} +export ORG_GRADLE_PROJECT_signing_password=${signing_password} export ORG_GRADLE_PROJECT_signing_secretKeyRingFile=${PROJECT_DIRECTORY}/secring.gpg -echo "Publishing snapshot with jdk8" -export JAVA_HOME="/opt/java/jdk8" +echo "Publishing snapshot with jdk11" +export JAVA_HOME="/opt/java/jdk11" SYSTEM_PROPERTIES="-Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.internal.http.connectionTimeout=120000 -Dorg.gradle.internal.http.socketTimeout=120000" diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.evergreen/test.sh b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.evergreen/test.sh index 01b8c28..3274e26 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.evergreen/test.sh +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.evergreen/test.sh @@ -5,10 +5,19 @@ set -o xtrace # Write all commands first to stderr set -o errexit # Exit the script with error if any of the commands fail + if [ "Windows_NT" = "$OS" ]; then - export JAVA_HOME=/cygdrive/c/java/jdk8 + export JDK8="/cygdrive/c/java/jdk8" + export JDK11="/cygdrive/c/java/jdk11" +else + export JDK8="/opt/java/jdk8" + export JDK11="/opt/java/jdk11" +fi + +if [ -d "$JDK11" ]; then + export JAVA_HOME=$JDK11 else - export JAVA_HOME=/opt/java/jdk8 + export JAVA_HOME=$JDK8 fi ./gradlew -version diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.gitignore b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.gitignore index e97dfb3..64e5adb 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.gitignore +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/.gitignore @@ -35,5 +35,5 @@ local.properties .java-version # bin -./bin - +/bin +/benchmarks/bin diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/benchmarks/build.gradle.kts b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/benchmarks/build.gradle.kts new file mode 100644 index 0000000..e499381 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/benchmarks/build.gradle.kts @@ -0,0 +1,28 @@ +/* + * Copyright 2023-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. + * + */ + +plugins { + id("application") +} + +application { + mainClass.set("com.mongodb.crypt.benchmark.BenchmarkRunner") +} + +dependencies { + implementation(project(":")) // Reference to the parent project +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/benchmarks/src/main/java/com/mongodb/crypt/benchmark/BenchmarkRunner.java b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/benchmarks/src/main/java/com/mongodb/crypt/benchmark/BenchmarkRunner.java new file mode 100644 index 0000000..e520557 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/benchmarks/src/main/java/com/mongodb/crypt/benchmark/BenchmarkRunner.java @@ -0,0 +1,217 @@ +/* + * Copyright 2023-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. + * + */ + +package com.mongodb.crypt.benchmark; + +import com.mongodb.crypt.capi.*; +import org.bson.*; + +import java.io.*; +import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.*; + +public class BenchmarkRunner { + static final int NUM_FIELDS = 1500; + static final int NUM_WARMUP_SECS = 2; + static final int NUM_SECS = 10; + static final byte[] LOCAL_MASTER_KEY = new byte[]{ + -99, -108, 75, 13, -109, -48, -59, 68, -91, 114, -3, 50, 27, -108, 48, -112, 35, 53, + 115, 124, -16, -10, -62, -12, -38, 35, 86, -25, -113, 4, -52, -6, -34, 117, -76, 81, + -121, -13, -117, -105, -41, 75, 68, 59, -84, 57, -94, -58, 77, -111, 0, 62, -47, -6, 74, + 48, -63, -46, -58, 94, -5, -84, 65, -14, 72, 19, 60, -101, 80, -4, -89, 36, 122, 46, 2, + 99, -93, -58, 22, 37, 81, 80, 120, 62, 15, -40, 110, -124, -90, -20, -115, 45, 36, 71, + -27, -81 + }; + + private static String getFileAsString(final String fileName) { + try { + URL resource = BenchmarkRunner.class.getResource("/" + fileName); + if (resource == null) { + throw new RuntimeException("Could not find file " + fileName); + } + return new String(Files.readAllBytes(Paths.get(resource.toURI()))); + } catch (Throwable t) { + throw new RuntimeException("Could not parse file " + fileName, t); + } + } + + private static BsonDocument getResourceAsDocument(final String fileName) { + return BsonDocument.parse(getFileAsString(fileName)); + } + + private static MongoCrypt createMongoCrypt() { + return MongoCrypts.create(MongoCryptOptions + .builder() + .localKmsProviderOptions(MongoLocalKmsProviderOptions.builder() + .localMasterKey(ByteBuffer.wrap(LOCAL_MASTER_KEY)) + .build()) + .build()); + } + + // DecryptTask decrypts a document repeatedly for a specified number of seconds and records ops/sec. + private static class DecryptTask implements Runnable { + public DecryptTask (MongoCrypt mongoCrypt, BsonDocument toDecrypt, int numSecs, CountDownLatch doneSignal) { + this.mongoCrypt = mongoCrypt; + this.toDecrypt = toDecrypt; + this.opsPerSecs = new ArrayList(numSecs); + this.numSecs = numSecs; + this.doneSignal = doneSignal; + } + public void run() { + for (int i = 0; i < numSecs; i++) { + long opsPerSec = 0; + long start = System.nanoTime(); + // Run for one second. + while (System.nanoTime() - start < 1_000_000_000) { + try (MongoCryptContext ctx = mongoCrypt.createDecryptionContext(toDecrypt)) { + assert ctx.getState() == MongoCryptContext.State.READY; + ctx.finish(); + opsPerSec++; + } + } + opsPerSecs.add(opsPerSec); + } + doneSignal.countDown(); + } + public long getMedianOpsPerSecs () { + if (opsPerSecs.size() == 0) { + throw new IllegalStateException("opsPerSecs is empty. Was `run` called?"); + } + Collections.sort(opsPerSecs); + return opsPerSecs.get(numSecs / 2); + } + private MongoCrypt mongoCrypt; + private BsonDocument toDecrypt; + private ArrayList opsPerSecs; + private int numSecs; + private CountDownLatch doneSignal; + } + public static void main(String[] args) throws IOException, InterruptedException, ExecutionException { + System.out.printf("BenchmarkRunner is using libmongocrypt version=%s, NUM_WARMUP_SECS=%d, NUM_SECS=%d%n", CAPI.mongocrypt_version(null).toString(), NUM_WARMUP_SECS, NUM_SECS); + // `keyDocument` is a Data Encryption Key (DEK) encrypted with the Key Encryption Key (KEK) `LOCAL_MASTER_KEY`. + BsonDocument keyDocument = getResourceAsDocument("keyDocument.json"); + try (MongoCrypt mongoCrypt = createMongoCrypt()) { + // `encrypted` will contain encrypted fields. + BsonDocument encrypted = new BsonDocument(); + { + for (int i = 0; i < NUM_FIELDS; i++) { + MongoExplicitEncryptOptions options = MongoExplicitEncryptOptions.builder() + .keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, Base64.getDecoder().decode("YWFhYWFhYWFhYWFhYWFhYQ=="))) + .algorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") + .build(); + BsonDocument toEncrypt = new BsonDocument("v", new BsonString(String.format("value %04d", i))); + try (MongoCryptContext ctx = mongoCrypt.createExplicitEncryptionContext(toEncrypt, options)) { + // If mongocrypt_t has not yet cached the DEK, supply it. + if (MongoCryptContext.State.NEED_MONGO_KEYS == ctx.getState()) { + ctx.addMongoOperationResult(keyDocument); + ctx.completeMongoOperation(); + } + assert ctx.getState() == MongoCryptContext.State.READY; + RawBsonDocument result = ctx.finish(); + BsonValue encryptedValue = result.get("v"); + String key = String.format("key%04d", i); + encrypted.append(key, encryptedValue); + } + } + } + + // Warm up benchmark and discard the result. + DecryptTask warmup = new DecryptTask(mongoCrypt, encrypted, NUM_WARMUP_SECS, new CountDownLatch(1)); + warmup.run(); + + // Decrypt `encrypted` and measure ops/sec. + // Check with varying thread counts to measure impact of a shared pool of Cipher instances. + int[] threadCounts = {1,2,8,64}; + ArrayList totalMedianOpsPerSecs = new ArrayList(threadCounts.length); + ArrayList createdAts = new ArrayList(threadCounts.length); + ArrayList completedAts = new ArrayList(threadCounts.length); + + for (int threadCount : threadCounts) { + ExecutorService executorService = Executors.newFixedThreadPool(threadCount); + CountDownLatch doneSignal = new CountDownLatch(threadCount); + ArrayList decryptTasks = new ArrayList(threadCount); + createdAts.add(ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + + for (int i = 0; i < threadCount; i++) { + DecryptTask decryptTask = new DecryptTask(mongoCrypt, encrypted, NUM_SECS, doneSignal); + decryptTasks.add(decryptTask); + executorService.submit(decryptTask); + } + + // Await completion of all tasks. Tasks are expected to complete shortly after NUM_SECS. Time out `await` if time exceeds 2 * NUM_SECS. + boolean ok = doneSignal.await(NUM_SECS * 2, TimeUnit.SECONDS); + assert ok; + completedAts.add(ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + // Sum the median ops/secs of all tasks to get total throughput. + long totalMedianOpsPerSec = 0; + for (DecryptTask decryptTask : decryptTasks) { + totalMedianOpsPerSec += decryptTask.getMedianOpsPerSecs(); + } + System.out.printf("threadCount=%d. Decrypting 1500 fields median ops/sec : %d%n", threadCount, totalMedianOpsPerSec); + totalMedianOpsPerSecs.add(totalMedianOpsPerSec); + executorService.shutdown(); + ok = executorService.awaitTermination(NUM_SECS * 2, TimeUnit.SECONDS); + assert ok; + } + + // Print the results in JSON that can be accepted by the `perf.send` command. + // See https://docs.devprod.prod.corp.mongodb.com/evergreen/Project-Configuration/Project-Commands#perfsend for the expected `perf.send` input. + ArrayList resultsArray = new ArrayList(threadCounts.length); + for (int i = 0; i < threadCounts.length; i++) { + int threadCount = threadCounts[i]; + long totalMedianOpsPerSec = totalMedianOpsPerSecs.get(i); + String createdAt = createdAts.get(i); + String completedAt = completedAts.get(i); + + resultsArray.add(new BsonDocument() + .append("info", new BsonDocument() + .append("test_name", new BsonString("java_decrypt_1500")) + .append("args", new BsonDocument() + .append("threadCount", new BsonInt32(threadCount)))) + .append("created_at", new BsonString(createdAt)) + .append("completed_at", new BsonString(completedAt)) + .append("artifacts", new BsonArray()) + .append("metrics", new BsonArray(Arrays.asList( + new BsonDocument() + .append("name", new BsonString("medianOpsPerSec")) + .append("type", new BsonString("THROUGHPUT")) + .append("value", new BsonInt64(totalMedianOpsPerSec)) + ))) + .append("sub_tests", new BsonArray())); + } + + BsonDocument results = new BsonDocument().append("results", new BsonArray(resultsArray)); + String resultsString = results.toJson(); + // Remove the prefix and suffix when writing to a file so only the [ ... ] array is included. + resultsString = resultsString.substring("{\"results\": ".length(), resultsString.length() - 1); + + String resultsFilePath = "results.json"; + try (OutputStreamWriter fileWriter = new OutputStreamWriter(new FileOutputStream(resultsFilePath), StandardCharsets.UTF_8)) { + fileWriter.write(resultsString); + } + System.out.println("Results written to file: " + resultsFilePath); + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/benchmarks/src/main/resources/keyDocument.json b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/benchmarks/src/main/resources/keyDocument.json new file mode 100644 index 0000000..20d631d --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/benchmarks/src/main/resources/keyDocument.json @@ -0,0 +1,24 @@ +{ + "_id": { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "ACR7Hm33dDOAAD7l2ubZhSpSUWK8BkALUY+qW3UgBAEcTV8sBwZnaAWnzDsmrX55dgmYHWfynDlJogC/e33u6pbhyXvFTs5ow9OLCuCWBJ39T/Ivm3kMaZJybkejY0V+uc4UEdHvVVz/SbitVnzs2WXdMGmo1/HmDRrxGYZjewFslquv8wtUHF5pyB+QDlQBd/al9M444/8bJZFbMSmtIg==", + "subType": "00" + } + }, + "creationDate": { + "$date": "2023-08-21T14:28:20.875Z" + }, + "updateDate": { + "$date": "2023-08-21T14:28:20.875Z" + }, + "status": 0, + "masterKey": { + "provider": "local" + } +} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/build.gradle.kts b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/build.gradle.kts index 0509dc4..dd9ce02 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/build.gradle.kts +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/build.gradle.kts @@ -37,25 +37,32 @@ plugins { id("biz.aQute.bnd.builder") version "6.2.0" } -repositories { - mavenCentral() - google() +allprojects { + repositories { + mavenCentral() + google() + } } group = "org.mongodb" -version = "1.8.0-SNAPSHOT" +version = "1.11.0-SNAPSHOT" description = "MongoDB client-side crypto support" java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 + + registerFeature("loggingSupport") { + usingSourceSet(sourceSets["main"]) + } } + val bsonRangeVersion = "[3.10,5.0)" dependencies { api("org.mongodb:bson:$bsonRangeVersion") api("net.java.dev.jna:jna:5.11.0") - implementation("org.slf4j:slf4j-api:1.7.36") + "loggingSupportImplementation"("org.slf4j:slf4j-api:1.7.36") // Tests testImplementation(platform("org.junit:junit-bom:5.8.2")) @@ -122,11 +129,17 @@ tasks.register("downloadJava") { overwrite(true) } +// The `processResources` task (defined by the `java-library` plug-in) consumes files in the main source set. +// Add a dependency on `unzipJava`. `unzipJava` adds libmongocrypt libraries to the main source set. +tasks.processResources { + mustRunAfter(tasks.named("unzipJava")) +} + tasks.register("unzipJava") { outputs.upToDateWhen { false } from(tarTree(resources.gzip("${jnaDownloadsDir}/libmongocrypt-java.tar.gz"))) include(jnaMapping.keys.flatMap { - listOf("${it}/nocrypto/**/libmongocrypt.so", "${it}/nocrypto/**/libmongocrypt.dylib", "${it}/nocrypto/**/mongocrypt.dll" ) + listOf("${it}/nocrypto/**/libmongocrypt.so", "${it}/lib/**/libmongocrypt.dylib", "${it}/bin/**/mongocrypt.dll" ) }) eachFile { path = "${jnaMapping[path.substringBefore("/")]}/${name}" @@ -209,6 +222,8 @@ publishing { create("mavenJava") { artifactId = "mongodb-crypt" from(components["java"]) + suppressPomMetadataWarningsFor("loggingSupportApiElements") + suppressPomMetadataWarningsFor("loggingSupportRuntimeElements") artifact(tasks["sourcesJar"]) artifact(tasks["javadocJar"]) diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.jar b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf..41d9927 100644 Binary files a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.jar and b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.jar differ diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.properties b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.properties index b1159fc..17655d0 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.properties +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradlew b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradlew index 8e25e6c..1b6c787 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradlew +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradlew.bat b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradlew.bat index 24467a1..ac1b06f 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradlew.bat +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/gradlew.bat @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/settings.gradle.kts b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/settings.gradle.kts new file mode 100644 index 0000000..29d8780 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/settings.gradle.kts @@ -0,0 +1 @@ +include("benchmarks") diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPI.java b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPI.java index 0162f94..999190b 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPI.java +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPI.java @@ -73,6 +73,31 @@ public static class mongocrypt_opts_t extends PointerType { * mongocrypt_binary_destroy. */ public static class mongocrypt_binary_t extends PointerType { + // The `mongocrypt_binary_t` struct layout is part of libmongocrypt's ABI: + // typedef struct _mongocrypt_binary_t { + // void *data; + // uint32_t len; + // } mongocrypt_binary_t; + // To improve performance, fields are read directly using `getPointer` and `getInt`. + // This results in observed performance improvements over using of `mongocrypt_binary_data` and `mongocrypt_binary_len`. Refer: MONGOCRYPT-589. + public mongocrypt_binary_t() { + super(); + } + public Pointer data() { + return this.getPointer().getPointer(0); + } + public int len() { + int len = this.getPointer().getInt(Native.POINTER_SIZE); + // mongocrypt_binary_t represents length as an unsigned `uint32_t`. + // Representing `uint32_t` values greater than INT32_MAX is represented as a negative `int`. + // Throw an exception. mongocrypt_binary_t is not expected to use lengths greater than INT32_MAX. + if (len < 0) { + throw new AssertionError( + String.format("Expected mongocrypt_binary_t length to be non-negative, got: %d", len)); + } + return len; + + } } /** @@ -558,9 +583,8 @@ public interface mongocrypt_random_fn extends Callback { mongocrypt_ctx_setopt_query_type (mongocrypt_ctx_t ctx, cstring query_type, int len); /** - * Set options for explicit encryption with the "rangePreview" algorithm. - * NOTE: The RangePreview algorithm is experimental only. It is not intended for - * public use. + * Set options for explicit encryption with the "range" algorithm. + * NOTE: "range" is currently unstable API and subject to backwards breaking changes. * * opts is a BSON document of the form: * { @@ -568,6 +592,7 @@ public interface mongocrypt_random_fn extends Callback { * "max": Optional<BSON value>, * "sparsity": Int64, * "precision": Optional<Int32> + * "trimFactor": Optional<Int32> * } * * @param ctx The @ref mongocrypt_ctx_t object. @@ -598,6 +623,17 @@ public interface mongocrypt_random_fn extends Callback { public static native boolean mongocrypt_status(mongocrypt_t crypt, mongocrypt_status_t status); + /** + * Returns true if libmongocrypt was built with native crypto support. + * + *

+ * If libmongocrypt was not built with native crypto support, setting crypto hooks is required. + *

+ * + * @return true if libmongocrypt was built with native crypto support + */ + public static native boolean + mongocrypt_is_crypto_available(); /** * Destroy the @ref mongocrypt_t object. @@ -850,9 +886,8 @@ public interface mongocrypt_random_fn extends Callback { /** * Explicit helper method to encrypt a Match Expression or Aggregate Expression. * Contexts created for explicit encryption will not go through mongocryptd. - * Requires query_type to be "rangePreview". - * NOTE: The RangePreview algorithm is experimental only. It is not intended for - * public use. + * Requires query_type to be "range". + * NOTE: "range" is currently unstable API and subject to backwards breaking changes. * * This method expects the passed-in BSON to be of the form: * { "v" : FLE2RangeFindDriverSpec } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPIHelper.java b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPIHelper.java index 64c2e47..e836210 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPIHelper.java +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CAPIHelper.java @@ -70,8 +70,8 @@ static BinaryHolder toBinary(final ByteBuffer buffer) { } static ByteBuffer toByteBuffer(final mongocrypt_binary_t binary) { - Pointer pointer = mongocrypt_binary_data(binary); - int length = mongocrypt_binary_len(binary); + Pointer pointer = binary.data(); + int length = binary.len(); return pointer.getByteBuffer(0, length); } @@ -83,11 +83,11 @@ static byte[] toByteArray(final mongocrypt_binary_t binary) { } static void writeByteArrayToBinary(final mongocrypt_binary_t binary, byte[] bytes) { - if (mongocrypt_binary_len(binary) < bytes.length) { + if (binary.len() < bytes.length) { throw new IllegalArgumentException(format("mongocrypt binary of length %d is not large enough to hold %d bytes", - mongocrypt_binary_len(binary), bytes.length)); + binary.len(), bytes.length)); } - Pointer outPointer = mongocrypt_binary_data(binary); + Pointer outPointer = binary.data(); outPointer.write(0, bytes, 0, bytes.length); } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CipherCallback.java b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CipherCallback.java index 68abfc0..b10c0f2 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CipherCallback.java +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/CipherCallback.java @@ -24,8 +24,11 @@ import com.sun.jna.Pointer; import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.ConcurrentLinkedDeque; import static com.mongodb.crypt.capi.CAPI.MONGOCRYPT_STATUS_ERROR_CLIENT; import static com.mongodb.crypt.capi.CAPI.mongocrypt_status_set; @@ -36,21 +39,24 @@ class CipherCallback implements mongocrypt_crypto_fn { private final String algorithm; private final String transformation; private final int mode; + private final CipherPool cipherPool; CipherCallback(final String algorithm, final String transformation, final int mode) { this.algorithm = algorithm; this.transformation = transformation; this.mode = mode; + this.cipherPool = new CipherPool(); } @Override public boolean crypt(final Pointer ctx, final mongocrypt_binary_t key, final mongocrypt_binary_t iv, final mongocrypt_binary_t in, final mongocrypt_binary_t out, final Pointer bytesWritten, final mongocrypt_status_t status) { + Cipher cipher = null; try { IvParameterSpec ivParameterSpec = new IvParameterSpec(toByteArray(iv)); SecretKeySpec secretKeySpec = new SecretKeySpec(toByteArray(key), algorithm); - Cipher cipher = Cipher.getInstance(transformation); + cipher = cipherPool.get(); cipher.init(mode, secretKeySpec, ivParameterSpec); byte[] result = cipher.doFinal(toByteArray(in)); @@ -61,6 +67,26 @@ public boolean crypt(final Pointer ctx, final mongocrypt_binary_t key, final mon } catch (Exception e) { mongocrypt_status_set(status, MONGOCRYPT_STATUS_ERROR_CLIENT, 0, new cstring(e.toString()), -1); return false; + } finally { + if (cipher != null) { + cipherPool.release(cipher); + } + } + } + + private class CipherPool { + private final ConcurrentLinkedDeque available = new ConcurrentLinkedDeque<>(); + + Cipher get() throws NoSuchAlgorithmException, NoSuchPaddingException { + Cipher cipher = available.pollLast(); + if (cipher != null) { + return cipher; + } + return Cipher.getInstance(transformation); + } + + void release(final Cipher cipher) { + available.addLast(cipher); } } } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoCryptImpl.java b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoCryptImpl.java index 7cf6f0d..2132f3c 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoCryptImpl.java +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoCryptImpl.java @@ -57,6 +57,7 @@ import static com.mongodb.crypt.capi.CAPI.mongocrypt_ctx_setopt_query_type; import static com.mongodb.crypt.capi.CAPI.mongocrypt_destroy; import static com.mongodb.crypt.capi.CAPI.mongocrypt_init; +import static com.mongodb.crypt.capi.CAPI.mongocrypt_is_crypto_available; import static com.mongodb.crypt.capi.CAPI.mongocrypt_new; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_aes_256_ctr; import static com.mongodb.crypt.capi.CAPI.mongocrypt_setopt_append_crypt_shared_lib_search_path; @@ -118,25 +119,39 @@ class MongoCryptImpl implements MongoCrypt { configure(() -> mongocrypt_setopt_log_handler(wrapped, logCallback, null)); - // We specify NoPadding here because the underlying C library is responsible for padding prior - // to executing the callback - aesCBC256EncryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.ENCRYPT_MODE); - aesCBC256DecryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.DECRYPT_MODE); - aesCTR256EncryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.ENCRYPT_MODE); - aesCTR256DecryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.DECRYPT_MODE); - - hmacSha512Callback = new MacCallback("HmacSHA512"); - hmacSha256Callback = new MacCallback("HmacSHA256"); - sha256Callback = new MessageDigestCallback("SHA-256"); - secureRandomCallback = new SecureRandomCallback(new SecureRandom()); - - configure(() -> mongocrypt_setopt_crypto_hooks(wrapped, aesCBC256EncryptCallback, aesCBC256DecryptCallback, - secureRandomCallback, hmacSha512Callback, hmacSha256Callback, - sha256Callback, null)); - - signingRSAESPKCSCallback = new SigningRSAESPKCSCallback(); - configure(() -> mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(wrapped, signingRSAESPKCSCallback, null)); - configure(() -> mongocrypt_setopt_aes_256_ctr(wrapped, aesCTR256EncryptCallback, aesCTR256DecryptCallback, null)); + if (mongocrypt_is_crypto_available()) { + LOGGER.debug("libmongocrypt is compiled with cryptography support, so not registering Java callbacks"); + aesCBC256EncryptCallback = null; + aesCBC256DecryptCallback = null; + aesCTR256EncryptCallback = null; + aesCTR256DecryptCallback = null; + hmacSha512Callback = null; + hmacSha256Callback = null; + sha256Callback = null; + secureRandomCallback = null; + signingRSAESPKCSCallback = null; + } else { + LOGGER.debug("libmongocrypt is compiled without cryptography support, so registering Java callbacks"); + // We specify NoPadding here because the underlying C library is responsible for padding prior + // to executing the callback + aesCBC256EncryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.ENCRYPT_MODE); + aesCBC256DecryptCallback = new CipherCallback("AES", "AES/CBC/NoPadding", Cipher.DECRYPT_MODE); + aesCTR256EncryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.ENCRYPT_MODE); + aesCTR256DecryptCallback = new CipherCallback("AES", "AES/CTR/NoPadding", Cipher.DECRYPT_MODE); + + hmacSha512Callback = new MacCallback("HmacSHA512"); + hmacSha256Callback = new MacCallback("HmacSHA256"); + sha256Callback = new MessageDigestCallback("SHA-256"); + secureRandomCallback = new SecureRandomCallback(new SecureRandom()); + + configure(() -> mongocrypt_setopt_crypto_hooks(wrapped, aesCBC256EncryptCallback, aesCBC256DecryptCallback, + secureRandomCallback, hmacSha512Callback, hmacSha256Callback, + sha256Callback, null)); + + signingRSAESPKCSCallback = new SigningRSAESPKCSCallback(); + configure(() -> mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(wrapped, signingRSAESPKCSCallback, null)); + configure(() -> mongocrypt_setopt_aes_256_ctr(wrapped, aesCTR256EncryptCallback, aesCTR256DecryptCallback, null)); + } if (options.getLocalKmsProviderOptions() != null) { try (BinaryHolder localMasterKeyBinaryHolder = toBinary(options.getLocalKmsProviderOptions().getLocalMasterKey())) { diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoExplicitEncryptOptions.java b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoExplicitEncryptOptions.java index 7dbe236..e96808e 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoExplicitEncryptOptions.java +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/java/com/mongodb/crypt/capi/MongoExplicitEncryptOptions.java @@ -114,7 +114,7 @@ public Builder queryType(final String queryType) { /** * The Range Options. * - *

It is an error to set rangeOptions when the algorithm is not "rangePreview".

+ *

It is an error to set rangeOptions when the algorithm is not "range".

* * @param rangeOptions the range options * @return this @@ -202,11 +202,13 @@ private MongoExplicitEncryptOptions(Builder builder) { this.contentionFactor = builder.contentionFactor; this.queryType = builder.queryType; this.rangeOptions = builder.rangeOptions; - if (!(Objects.equals(algorithm, "Indexed") || Objects.equals(algorithm, "RangePreview"))) { + if (!(Objects.equals(algorithm, "Indexed") || Objects.equals(algorithm, "Range"))) { if (contentionFactor != null) { - throw new IllegalStateException("Invalid configuration, contentionFactor can only be set if algorithm is 'Indexed' or 'RangePreview'"); + throw new IllegalStateException( + "Invalid configuration, contentionFactor can only be set if algorithm is 'Indexed' or 'Range'"); } else if (queryType != null) { - throw new IllegalStateException("Invalid configuration, queryType can only be set if algorithm is 'Indexed' or 'RangePreview'"); + throw new IllegalStateException( + "Invalid configuration, queryType can only be set if algorithm is 'Indexed' or 'Range'"); } } } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/resources/META-INF/native-image/jni-config.json b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/resources/META-INF/native-image/jni-config.json new file mode 100644 index 0000000..44e398c --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/resources/META-INF/native-image/jni-config.json @@ -0,0 +1,180 @@ +[ +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_crypto_fn", + "methods":[{"name":"crypt","parameterTypes":["com.sun.jna.Pointer","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","com.sun.jna.Pointer","com.mongodb.crypt.capi.CAPI$mongocrypt_status_t"] }] +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_hash_fn", + "methods":[{"name":"hash","parameterTypes":["com.sun.jna.Pointer","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","com.mongodb.crypt.capi.CAPI$mongocrypt_status_t"] }] +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_hmac_fn", + "methods":[{"name":"hmac","parameterTypes":["com.sun.jna.Pointer","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","com.mongodb.crypt.capi.CAPI$mongocrypt_status_t"] }] +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_log_fn_t", + "methods":[{"name":"log","parameterTypes":["int","com.mongodb.crypt.capi.CAPI$cstring","int","com.sun.jna.Pointer"] }] +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_random_fn", + "methods":[{"name":"random","parameterTypes":["com.sun.jna.Pointer","com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t","int","com.mongodb.crypt.capi.CAPI$mongocrypt_status_t"] }] +}, +{ + "name":"com.sun.jna.Callback" +}, +{ + "name":"com.sun.jna.CallbackReference", + "methods":[{"name":"getCallback","parameterTypes":["java.lang.Class","com.sun.jna.Pointer","boolean"] }, {"name":"getFunctionPointer","parameterTypes":["com.sun.jna.Callback","boolean"] }, {"name":"getNativeString","parameterTypes":["java.lang.Object","boolean"] }, {"name":"initializeThread","parameterTypes":["com.sun.jna.Callback","com.sun.jna.CallbackReference$AttachOptions"] }] +}, +{ + "name":"com.sun.jna.CallbackReference$AttachOptions" +}, +{ + "name":"com.sun.jna.FromNativeConverter", + "methods":[{"name":"nativeType","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.IntegerType", + "fields":[{"name":"value"}] +}, +{ + "name":"com.sun.jna.JNIEnv" +}, +{ + "name":"com.sun.jna.Native", + "methods":[{"name":"dispose","parameterTypes":[] }, {"name":"fromNative","parameterTypes":["com.sun.jna.FromNativeConverter","java.lang.Object","java.lang.reflect.Method"] }, {"name":"fromNative","parameterTypes":["java.lang.Class","java.lang.Object"] }, {"name":"fromNative","parameterTypes":["java.lang.reflect.Method","java.lang.Object"] }, {"name":"nativeType","parameterTypes":["java.lang.Class"] }, {"name":"toNative","parameterTypes":["com.sun.jna.ToNativeConverter","java.lang.Object"] }] +}, +{ + "name":"com.sun.jna.Native$ffi_callback", + "methods":[{"name":"invoke","parameterTypes":["long","long","long"] }] +}, +{ + "name":"com.sun.jna.NativeMapped", + "methods":[{"name":"toNative","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.Pointer", + "fields":[{"name":"peer"}], + "methods":[{"name":"","parameterTypes":["long"] }] +}, +{ + "name":"com.sun.jna.PointerType", + "fields":[{"name":"pointer"}] +}, +{ + "name":"com.sun.jna.Structure", + "fields":[{"name":"memory"}, {"name":"typeInfo"}], + "methods":[{"name":"autoRead","parameterTypes":[] }, {"name":"autoWrite","parameterTypes":[] }, {"name":"getTypeInfo","parameterTypes":[] }, {"name":"newInstance","parameterTypes":["java.lang.Class","long"] }] +}, +{ + "name":"com.sun.jna.Structure$ByValue" +}, +{ + "name":"com.sun.jna.Structure$FFIType$FFITypes", + "fields":[{"name":"ffi_type_double"}, {"name":"ffi_type_float"}, {"name":"ffi_type_longdouble"}, {"name":"ffi_type_pointer"}, {"name":"ffi_type_sint16"}, {"name":"ffi_type_sint32"}, {"name":"ffi_type_sint64"}, {"name":"ffi_type_sint8"}, {"name":"ffi_type_uint16"}, {"name":"ffi_type_uint32"}, {"name":"ffi_type_uint64"}, {"name":"ffi_type_uint8"}, {"name":"ffi_type_void"}] +}, +{ + "name":"com.sun.jna.WString", + "methods":[{"name":"","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Boolean", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["boolean"] }, {"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Byte", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["byte"] }] +}, +{ + "name":"java.lang.Character", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["char"] }] +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"getComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.Double", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["double"] }] +}, +{ + "name":"java.lang.Float", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["float"] }] +}, +{ + "name":"java.lang.Integer", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.Long", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["long"] }] +}, +{ + "name":"java.lang.Object", + "methods":[{"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.Short", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["short"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"","parameterTypes":["byte[]"] }, {"name":"","parameterTypes":["byte[]","java.lang.String"] }, {"name":"getBytes","parameterTypes":[] }, {"name":"getBytes","parameterTypes":["java.lang.String"] }, {"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }, {"name":"toCharArray","parameterTypes":[] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"java.lang.UnsatisfiedLinkError", + "methods":[{"name":"","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Void", + "fields":[{"name":"TYPE"}] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getParameterTypes","parameterTypes":[] }, {"name":"getReturnType","parameterTypes":[] }] +}, +{ + "name":"java.nio.Buffer", + "methods":[{"name":"position","parameterTypes":[] }] +}, +{ + "name":"java.nio.ByteBuffer", + "methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }] +}, +{ + "name":"java.nio.CharBuffer", + "methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }] +}, +{ + "name":"java.nio.DoubleBuffer", + "methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }] +}, +{ + "name":"java.nio.FloatBuffer", + "methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }] +}, +{ + "name":"java.nio.IntBuffer", + "methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }] +}, +{ + "name":"java.nio.LongBuffer", + "methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }] +}, +{ + "name":"java.nio.ShortBuffer", + "methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }] +} +] diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/resources/META-INF/native-image/reflect-config.json b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/resources/META-INF/native-image/reflect-config.json new file mode 100644 index 0000000..4187c0e --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/main/resources/META-INF/native-image/reflect-config.json @@ -0,0 +1,134 @@ +[ +{ + "name":"com.mongodb.crypt.capi.CAPI", + "allPublicFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$cstring", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_binary_t", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_crypto_fn", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_ctx_t", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_hash_fn", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_hmac_fn", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_kms_ctx_t", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_log_fn_t", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_random_fn", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_status_t", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.mongodb.crypt.capi.CAPI$mongocrypt_t", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.CallbackProxy", + "methods":[{"name":"callback","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"com.sun.jna.Pointer", + "fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}] +}, +{ + "name":"com.sun.jna.Structure$FFIType", + "allDeclaredFields":true, + "queryAllPublicConstructors":true, + "fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}], + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.Structure$FFIType$size_t", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.ptr.PointerByReference", + "fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}], + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"boolean", + "fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}] +}, +{ + "name":"com.sun.crypto.provider.AESCipher$General", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.HmacCore$HmacSHA256", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.HmacCore$HmacSHA512", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"int", + "fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}] +}, +{ + "name":"java.lang.Throwable", + "methods":[{"name":"addSuppressed","parameterTypes":["java.lang.Throwable"] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"isVarArgs","parameterTypes":[] }] +}, +{ + "name":"java.nio.Buffer" +}, +{ + "name":"long", + "fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA2$SHA256", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA5$SHA512", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"void", + "fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}] +}, +{ + "name":"org.slf4j.Logger" +} +] diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/java/com/mongodb/crypt/capi/MongoCryptTest.java b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/java/com/mongodb/crypt/capi/MongoCryptTest.java index 969a60a..b9424cd 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/java/com/mongodb/crypt/capi/MongoCryptTest.java +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/java/com/mongodb/crypt/capi/MongoCryptTest.java @@ -44,6 +44,7 @@ import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; @SuppressWarnings("SameParameterValue") @@ -210,8 +211,8 @@ public void testExplicitExpressionEncryption() { MongoExplicitEncryptOptions options = MongoExplicitEncryptOptions.builder() .keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, Base64.getDecoder().decode("q83vqxI0mHYSNBI0VniQEg=="))) - .algorithm("RangePreview") - .queryType("rangePreview") + .algorithm("Range") + .queryType("range") .contentionFactor(4L) .rangeOptions(rangeOptions) .build(); @@ -230,6 +231,47 @@ public void testExplicitExpressionEncryption() { mongoCrypt.close(); } + @Test + public void testRangePreviewQueryTypeIsNotSupported() { + MongoCrypt mongoCrypt = createMongoCrypt(); + assertNotNull(mongoCrypt); + + BsonDocument valueToEncrypt = getResourceAsDocument("fle2-find-range-explicit-v2/int32/value-to-encrypt.json"); + BsonDocument rangeOptions = getResourceAsDocument("fle2-find-range-explicit-v2/int32/rangeopts.json"); + + MongoExplicitEncryptOptions options = MongoExplicitEncryptOptions.builder() + .keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, Base64.getDecoder().decode("q83vqxI0mHYSNBI0VniQEg=="))) + .algorithm("Range") + .queryType("rangePreview") + .contentionFactor(4L) + .rangeOptions(rangeOptions) + .build(); + + MongoCryptException exp = assertThrows(MongoCryptException.class, () -> mongoCrypt.createEncryptExpressionContext(valueToEncrypt, options)); + assertEquals("Query type 'rangePreview' is deprecated, please use 'range'", exp.getMessage()); + mongoCrypt.close(); + } + + @Test + public void testRangePreviewAlgorithmIsNotSupported() { + MongoCrypt mongoCrypt = createMongoCrypt(); + assertNotNull(mongoCrypt); + + BsonDocument rangeOptions = getResourceAsDocument("fle2-find-range-explicit-v2/int32/rangeopts.json"); + + IllegalStateException illegalStateException = assertThrows(IllegalStateException.class, () -> MongoExplicitEncryptOptions.builder() + .keyId(new BsonBinary(BsonBinarySubType.UUID_STANDARD, Base64.getDecoder().decode("q83vqxI0mHYSNBI0VniQEg=="))) + .algorithm("RangePreview") + .queryType("range") + .contentionFactor(4L) + .rangeOptions(rangeOptions) + .build()); + + assertEquals("Invalid configuration, contentionFactor can only be set if algorithm is 'Indexed' or 'Range'", + illegalStateException.getMessage()); + mongoCrypt.close(); + } + @Test public void testExplicitEncryptionDecryptionKeyAltName() throws IOException, URISyntaxException { MongoCrypt mongoCrypt = createMongoCrypt(); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/encrypted-payload.json index 796f336..7db5540 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/encrypted-payload.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/encrypted-payload.json @@ -5,7 +5,7 @@ "age": { "$gte": { "$binary": { - "base64": "Dd0BAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAAA==", + "base64": "DQECAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAEnNwAAEAAAAAAAAAEHRmAAEAAAAQbW4AAAAAABBteADIAAAAAA==", "subType": "06" } } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/rangeopts.json b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/rangeopts.json index 5ef3da4..2e1407f 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/rangeopts.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/rangeopts.json @@ -7,5 +7,8 @@ }, "sparsity": { "$numberLong": "1" + }, + "trimFactor": { + "$numberInt": "1" } } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/.clang-format b/ext/libmongocrypt/libmongocrypt/bindings/node/.clang-format deleted file mode 100644 index 5b30f57..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/.clang-format +++ /dev/null @@ -1,15 +0,0 @@ -BasedOnStyle: Google -AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -BinPackArguments: false -BinPackParameters: false -ColumnLimit: 100 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -IndentWidth: 4 -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -SpaceBeforeAssignmentOperators: true -Standard: Cpp11 -UseTab: Never diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/.eslintrc.json b/ext/libmongocrypt/libmongocrypt/bindings/node/.eslintrc.json deleted file mode 100644 index 8938b77..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/.eslintrc.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "root": true, - "extends": [ - "eslint:recommended", - "plugin:prettier/recommended" - ], - "env": { - "node": true, - "mocha": true, - "es6": true - }, - "parserOptions": { - "ecmaVersion": 2019 - }, - "plugins": [ - "prettier" - ], - "rules": { - "no-restricted-properties": [ - "error", - { - "object": "describe", - "property": "only" - }, - { - "object": "it", - "property": "only" - }, - { - "object": "context", - "property": "only" - } - ], - "prettier/prettier": "error", - "no-console": "error", - "valid-typeof": "error", - "eqeqeq": ["error", "always", {"null": "ignore"}], - "strict": ["error", "global"], - "no-restricted-syntax": [ - "error", - { - "selector": "TSEnumDeclaration", - "message": "Do not declare enums" - }, - { - "selector": "BinaryExpression[operator=/[=!]==/] Identifier[name='undefined']", - "message": "Do not strictly check undefined" - }, - { - "selector": "BinaryExpression[operator=/[=!]==/] Literal[raw='null']", - "message": "Do not strictly check null" - }, - { - "selector": "BinaryExpression[operator=/[=!]==?/] Literal[value='undefined']", - "message": "Do not strictly check typeof undefined (NOTE: currently this rule only detects the usage of 'undefined' string literal so this could be a misfire)" - } - ] - }, - "overrides": [ - { - // Settings for javascript test files - "files": [ - "test/**/*.js" - ], - "rules": { - "no-console": "off", - "no-restricted-syntax": "off" - } - } - ] -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/init-nvm.sh b/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/init-nvm.sh deleted file mode 100644 index 28d14f1..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/init-nvm.sh +++ /dev/null @@ -1,13 +0,0 @@ -#! /usr/bin/env bash - -export PATH="/opt/mongodbtoolchain/v2/bin:$PATH" - -NODE_ARTIFACTS_PATH="${PROJECT_DIRECTORY}/node-artifacts" -if [[ "$OS" == "Windows_NT" ]]; then - NODE_ARTIFACTS_PATH=$(cygpath --unix "$NODE_ARTIFACTS_PATH") -fi - -export PATH="$NODE_ARTIFACTS_PATH/npm_global/bin:$NODE_ARTIFACTS_PATH/nodejs/bin:$PATH" -hash -r - -export NODE_OPTIONS="--trace-deprecation --trace-warnings" diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/install-dependencies.sh b/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/install-dependencies.sh deleted file mode 100644 index 1414891..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/install-dependencies.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env bash -set -o errexit # Exit the script with error if any of the commands fail - -NODE_LTS_NAME=${NODE_LTS_NAME:-fermium} -NODE_ARTIFACTS_PATH="${PROJECT_DIRECTORY:-$(pwd)}/node-artifacts" -if [[ "$OS" = "Windows_NT" ]]; then NODE_ARTIFACTS_PATH=$(cygpath --unix "$NODE_ARTIFACTS_PATH"); fi - -CURL_FLAGS=( - --fail # Exit code 1 if request fails - --compressed # Request a compressed response should keep fetching fast - --location # Follow a redirect - --retry 8 # Retry HTTP 408, 429, 500, 502, 503 or 504, 8 times - --silent # Do not print a progress bar - --show-error # Despite the silent flag still print out errors - --max-time 900 # 900 seconds is 15 minutes, evergreen times out at 20 - --continue-at - # If a download is interrupted it can figure out where to resume -) - -mkdir -p "$NODE_ARTIFACTS_PATH/npm_global" - -# Comparisons are all case insensitive -shopt -s nocasematch - -# index.tab is a sorted tab separated values file with the following headers -# 0 1 2 3 4 5 6 7 8 9 10 -# version date files npm v8 uv zlib openssl modules lts security -curl "${CURL_FLAGS[@]}" "https://nodejs.org/dist/index.tab" --output node_index.tab - -while IFS=$'\t' read -r -a row; do - node_index_version="${row[0]}" - node_index_date="${row[1]}" - node_index_lts="${row[9]}" - [[ "$node_index_version" = "version" ]] && continue # skip tsv header - [[ "$NODE_LTS_NAME" = "latest" ]] && break # first line is latest - [[ "$NODE_LTS_NAME" = "$node_index_lts" ]] && break # case insensitive compare -done < node_index.tab - -if [[ "$OS" = "Windows_NT" ]]; then - operating_system="win" -elif [[ $(uname) = "darwin" ]]; then - operating_system="darwin" -elif [[ $(uname) = "linux" ]]; then - operating_system="linux" -else - echo "Unable to determine operating system: $operating_system" - exit 1 -fi - -architecture=$(uname -m) -if [[ $architecture = "x86_64" ]]; then - architecture="x64" -elif [[ $architecture = "arm64" ]]; then - architecture="arm64" -elif [[ $architecture = "aarch64" ]]; then - architecture="arm64" -elif [[ $architecture == s390* ]]; then - architecture="s390x" -elif [[ $architecture == ppc* ]]; then - architecture="ppc64le" -else - echo "Unable to determine operating system: $architecture" - exit 1 -fi - -file_extension="tar.gz" -if [[ "$OS" = "Windows_NT" ]]; then file_extension="zip"; fi - -node_directory="node-${node_index_version}-${operating_system}-${architecture}" -node_archive="${node_directory}.${file_extension}" -node_archive_path="$NODE_ARTIFACTS_PATH/${node_archive}" -node_download_url="https://nodejs.org/dist/${node_index_version}/${node_archive}" - -echo "Node.js ${node_index_version} for ${operating_system}-${architecture} released on ${node_index_date}" - -set -o xtrace - -curl "${CURL_FLAGS[@]}" "${node_download_url}" --output "$node_archive_path" - -if [[ "$file_extension" = "zip" ]]; then - unzip -q "$node_archive_path" -d "${NODE_ARTIFACTS_PATH}" - mkdir -p "${NODE_ARTIFACTS_PATH}/nodejs" - # Windows "bins" are at the top level - mv "${NODE_ARTIFACTS_PATH}/${node_directory}" "${NODE_ARTIFACTS_PATH}/nodejs/bin" - # Need to add executable flag ourselves - chmod +x "${NODE_ARTIFACTS_PATH}/nodejs/bin/node.exe" - chmod +x "${NODE_ARTIFACTS_PATH}/nodejs/bin/npm" -else - tar -xf "$node_archive_path" -C "${NODE_ARTIFACTS_PATH}" - mv "${NODE_ARTIFACTS_PATH}/${node_directory}" "${NODE_ARTIFACTS_PATH}/nodejs" -fi - -export PATH="$NODE_ARTIFACTS_PATH/npm_global/bin:$NODE_ARTIFACTS_PATH/nodejs/bin:$PATH" -hash -r - -# Set npm -g prefix to our local artifacts directory -cat < .npmrc -prefix=$NODE_ARTIFACTS_PATH/npm_global -EOT - -if [[ $operating_system != "win" ]]; then - # Update npm to latest when we can - npm install --global npm@latest - hash -r -fi - -echo "npm version: $(npm -v)" - -# other repos that use this script run npm install after installing Node. -# we can't in mongodb-client-encryption, because when releasing -# npm install will attempt to build from source, which fails -# because we haven't built libmongocrypt yet. -# npm install "${NPM_OPTIONS}" diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/prebuild.sh b/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/prebuild.sh deleted file mode 100755 index 2840d40..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/prebuild.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env bash - -if [ -z ${DISTRO_ID+omitted} ]; then echo "DISTRO_ID is unset" && exit 1; fi - -set -o errexit -set +o xtrace - -# FLE platform matrix (as of Feb 8th 2022) -# macos arm64 (compiled on 11.00) -# macos x86_64 (compiled on 10.14) -# windows x86_64 (compiled on vs2017) -# linux x86_64 (releases on RHEL7) -# linux s390x -# linux arm64 - -# Determines the OS name through uname results -# Returns 'windows' 'linux' 'macos' or 'unknown' -os_name() { - local WINDOWS_REGEX="cygwin|windows|mingw|msys" - local UNAME - UNAME=$(uname | tr '[:upper:]' '[:lower:]') - - local OS_NAME="unknown" - - if [[ $UNAME =~ $WINDOWS_REGEX ]]; then - OS_NAME="windows" - elif [[ $UNAME == "darwin" ]]; then - OS_NAME="macos" - elif [[ $UNAME == "linux" ]]; then - OS_NAME="linux" - fi - - echo $OS_NAME -} - -OS=$(os_name) - -get_version_at_git_rev () { - local REV=$1 - local VERSION - VERSION=$(node -r child_process -e "console.log(JSON.parse(child_process.execSync('git show $REV:./package.json', { encoding: 'utf8' })).version);") - echo "$VERSION" -} - -run_prebuild() { - if [ -z ${NODE_GITHUB_TOKEN+omitted} ]; then echo "NODE_GITHUB_TOKEN is unset" && exit 1; fi - echo "Github token detected. Running prebuild." - npm run prebuild -- -u "$NODE_GITHUB_TOKEN" - echo "Prebuild's successfully submitted" -} - -VERSION_AT_HEAD=$(get_version_at_git_rev "HEAD") -VERSION_AT_HEAD_1=$(get_version_at_git_rev "HEAD~1") - -if [[ "$OS" == "macos" ]]; then - ARCH=$(uname -m) - if [[ "$ARCH" == "arm64" ]]; then - # TODO(NODE-5174): node-gyp fails to run prebuild if Python 3.11+ - echo "Exporting PYTHON location for version $(/opt/homebrew/opt/python@3.9/bin/python3.9 --version)" - export PYTHON="/opt/homebrew/opt/python@3.9/bin/python3.9" - fi -fi - -if [[ -n $NODE_FORCE_PUBLISH ]]; then - echo "\$NODE_FORCE_PUBLISH=${NODE_FORCE_PUBLISH} detected" - echo "Beginning prebuild" - run_prebuild -elif [[ "$VERSION_AT_HEAD" != "$VERSION_AT_HEAD_1" ]]; then - echo "Difference is package version ($VERSION_AT_HEAD_1 -> $VERSION_AT_HEAD)" - echo "Beginning prebuild" - - if [[ "$OS" == "linux" ]]; then - # Handle limiting which linux gets to publish prebuild - ARCH=$(uname -m) - - if [[ $DISTRO_ID == "rhel70-small" ]]; then - # only publish x86_64 linux prebuilds from RHEL 7 - run_prebuild - elif [[ "$ARCH" != "x86_64" ]]; then - # Non-x86 linux variants should just publish - run_prebuild - else - # Non RHEL 7 linux variants should just test the prebuild task - echo "Will prebuild without submit ($OS - $ARCH - $DISTRO_ID)" - npm run prebuild - fi - - exit 0 - fi - - # Windows and MacOS - run_prebuild -else - echo "No difference is package version ($VERSION_AT_HEAD_1 -> $VERSION_AT_HEAD)" - echo "Will prebuild without submit ($OS - $DISTRO_ID)" - npm run prebuild - echo "Local prebuild successful." -fi diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/test.sh b/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/test.sh deleted file mode 100755 index 32a4e6b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/.evergreen/test.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash - -# set -o xtrace # Write all commands first to stderr -set -o errexit # Exit the script with error if any of the commands fail - -echo "Setting up environment" - -export PATH="/opt/mongodbtoolchain/v2/bin:$PATH" -hash -r - -export NODE_LTS_NAME="gallium" -source ./.evergreen/install-dependencies.sh - - - -# Handle the circular dependency when testing with a real client. -MONGODB_CLIENT_ENCRYPTION_OVERRIDE="$(pwd)" -export MONGODB_CLIENT_ENCRYPTION_OVERRIDE - -# install node dependencies -echo "Installing package dependencies (includes a static build)" -bash ./etc/build-static.sh - -if [[ $OMIT_PEER_DEPS != "true" ]]; then - npm install '@aws-sdk/credential-providers' - npm install 'gcp-metadata' -fi - -# Run tests -echo "Running tests" -npm run check:lint -MONGODB_NODE_SKIP_LIVE_TESTS=true npm test - -# Run prebuild and deploy -echo "Running prebuild and deploy" -bash ./.evergreen/prebuild.sh diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/.gitignore b/ext/libmongocrypt/libmongocrypt/bindings/node/.gitignore deleted file mode 100644 index e316d06..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -lib-cov -*.seed -*.log -*.csv -*.dat -*.out -*.pid -*.gz -.DS_Store - -pids -logs -results -node_modules -build - -npm-debug.log -.vscode -deps -*.tgz - -xunit.xml diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/.mocharc.json b/ext/libmongocrypt/libmongocrypt/bindings/node/.mocharc.json deleted file mode 100644 index fc76a56..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/.mocharc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/mocharc.json", - "require": [ - "test/tools/chai-addons.js" - ], - "recursive": true, - "failZero": true, - "reporter": "test/tools/mongodb_reporter.js", - "color": true -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/.prettierrc.json b/ext/libmongocrypt/libmongocrypt/bindings/node/.prettierrc.json deleted file mode 100644 index 3ac41fb..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/.prettierrc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "singleQuote": true, - "tabWidth": 2, - "printWidth": 100, - "arrowParens": "avoid", - "trailingComma": "none" -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/CHANGELOG.md b/ext/libmongocrypt/libmongocrypt/bindings/node/CHANGELOG.md deleted file mode 100644 index 7ae90f6..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/CHANGELOG.md +++ /dev/null @@ -1,105 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. - -## [2.8.0-alpha.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.8.0-alpha.0...node-v2.8.0-alpha.1) (2023-04-27) - -## [2.8.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.7.1...node-v2.8.0-alpha.0) (2023-04-04) - -### [2.7.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.7.0...node-v2.7.1) (2023-03-20) - -## [2.7.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.7.0-alpha.0...node-v2.7.0) (2023-03-20) - -## [2.7.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.6.0...node-v2.7.0-alpha.0) (2023-03-14) - -## [2.6.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.6.0-alpha.0...node-v2.6.0) (2023-02-23) - -## [2.6.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.5.0...node-v2.6.0-alpha.0) (2023-02-16) - -## [2.5.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.4.0...node-v2.5.0) (2023-02-06) - -## [2.4.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.4.0-alpha.2...node-v2.4.0) (2023-01-26) - -## [2.4.0-alpha.2](https://github.com/mongodb/libmongocrypt/compare/node-v2.4.0-alpha.0...node-v2.4.0-alpha.2) (2023-01-24) - -## [2.4.0-alpha.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.4.0-alpha.0...node-v2.4.0-alpha.1) (2023-01-23) - -## [2.4.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.3.0...node-v2.4.0-alpha.0) (2023-01-20) - -## [2.3.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.1...node-v2.3.0) (2022-10-05) - -### [2.2.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0...node-v2.2.1) (2022-09-12) - -## [2.2.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.6...node-v2.2.0) (2022-08-10) - -## [2.2.0-alpha.6](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.5...node-v2.2.0-alpha.6) (2022-07-29) - -## [2.2.0-alpha.6](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.5...node-v2.2.0-alpha.6) (2022-07-29) - -## [2.2.0-alpha.5](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.4...node-v2.2.0-alpha.5) (2022-07-20) - -## [2.2.0-alpha.5](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.4...node-v2.2.0-alpha.5) (2022-07-20) - -## [2.2.0-alpha.4](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.3...node-v2.2.0-alpha.4) (2022-07-06) - -## [2.2.0-alpha.3](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.2...node-v2.2.0-alpha.3) (2022-06-23) - -## [2.2.0-alpha.2](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.1...node-v2.2.0-alpha.2) (2022-06-10) - -## [2.2.0-alpha.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.2.0-alpha.0...node-v2.2.0-alpha.1) (2022-06-01) - -## [2.2.0-alpha.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.1.0...node-v2.2.0-alpha.0) (2022-05-04) - -## [2.1.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0...node-v2.1.0) (2022-04-21) - -## [2.0.0](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.4...node-v2.0.0) (2022-02-17) - -## [2.0.0-beta.4](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.3...node-v2.0.0-beta.4) (2022-02-09) - -## [2.0.0-beta.3](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.0...node-v2.0.0-beta.3) (2022-01-31) - -## [2.0.0-beta.2](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.0...node-v2.0.0-beta.2) (2021-12-22) - -## [2.0.0-beta.1](https://github.com/mongodb/libmongocrypt/compare/node-v2.0.0-beta.0...node-v2.0.0-beta.1) (2021-12-21) - -## [2.0.0-beta.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.7...node-v2.0.0-beta.0) (2021-10-07) - -### [1.2.7](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.6...node-v1.2.7) (2021-09-14) - -### [1.2.6](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.5...node-v1.2.6) (2021-07-01) - -### [1.2.5](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.4...node-v1.2.5) (2021-06-10) - -### [1.2.4](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.3...node-v1.2.4) (2021-06-01) - -### [1.2.3](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.2...node-v1.2.3) (2021-04-06) - -### [1.2.2](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.1...node-v1.2.2) (2021-03-16) - -### [1.2.1](https://github.com/mongodb/libmongocrypt/compare/node-v1.2.0...node-v1.2.1) (2021-02-05) - -## [1.2.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.1.0...node-v1.2.0) (2021-02-02) - -### [1.1.1-beta.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.1.0...node-v1.1.1-beta.0) (2020-12-04) - -# [1.1.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.1...node-v1.1.0) (2020-06-23) - - - -## [1.0.1](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0...1.0.1) (2019-12-31) - - - -# [1.0.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0-rc3.0...1.0.0) (2019-12-10) - - - -# [1.0.0-rc3.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0-rc2.0...1.0.0-rc3.0) (2019-12-04) - - - -# [1.0.0-rc2.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0-rc1.0...1.0.0-rc2.0) (2019-12-04) - - - -# [1.0.0-rc1.0](https://github.com/mongodb/libmongocrypt/compare/node-v1.0.0-rc0...1.0.0-rc1.0) (2019-12-04) diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/LICENSE b/ext/libmongocrypt/libmongocrypt/bindings/node/LICENSE deleted file mode 100644 index 261eeb9..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/README.md b/ext/libmongocrypt/libmongocrypt/bindings/node/README.md index 3eaacee..035cd1e 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/README.md +++ b/ext/libmongocrypt/libmongocrypt/bindings/node/README.md @@ -1,902 +1,6 @@ -MongoDB Client Encryption -========================= +### The Node.js Bindings Have Moved! -The Node.js wrapper for [`libmongocrypt`](../../README.md) - -### Installation - -You can install `mongodb-client-encryption` with the following: - -```bash -npm install mongodb-client-encryption -``` - -### Development -#### Setup - -Run the following command to build libmongocrypt and setup the node bindings for development: - -```shell -bash ./etc/build-static.sh -``` - - -#### Testing - -Some tests require a standalone server to be running with authentication enabled. Set up a single -server running with the following conditions: - -| param | value | -|-----------|-----------| -| host | localhost | -| port | 27017 | - -This is the standard setup for a standalone server with no authentication. - -Run the test suite using: - -```bash -npm test -``` - -# Documentation - -## Classes - -
-
AutoEncrypter
-

An internal class to be used by the driver for auto encryption -NOTE: Not meant to be instantiated directly, this is for internal use only.

-
-
ClientEncryption
-

The public interface for explicit in-use encryption

-
-
MongoCryptError
-

An error indicating that something went wrong specifically with MongoDB Client Encryption

-
-
MongoCryptCreateDataKeyError
-

An error indicating that ClientEncryption.createEncryptedCollection() failed to create data keys

-
-
MongoCryptCreateEncryptedCollectionError
-

An error indicating that ClientEncryption.createEncryptedCollection() failed to create a collection

-
-
MongoCryptAzureKMSRequestError
-

An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials.

-
-
- -## Typedefs - -
-
BSONValue : *
-

any serializable BSON value

-
-
Long : BSON.Long
-

A 64 bit integer, represented by the js-bson Long type.

-
-
KMSProviders : object
-

Configuration options that are used by specific KMS providers during key generation, encryption, and decryption.

-
-
DataKey : object
-

A data key as stored in the database.

-
-
KmsProvider : string
-

A string containing the name of a kms provider. Valid options are 'aws', 'azure', 'gcp', 'kmip', or 'local'

-
-
ClientSession : object
-

The ClientSession class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/ClientSession.html)

-
-
DeleteResult : object
-

The result of a delete operation from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/interfaces/DeleteResult.html)

-
-
BulkWriteResult : object
-

The BulkWriteResult class from the MongoDB Node driver (https://mongodb.github.io/node-mongodb-native/4.8/classes/BulkWriteResult.html)

-
-
FindCursor : object
-

The FindCursor class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/FindCursor.html)

-
-
ClientEncryptionDataKeyId : Binary
-

The id of an existing dataKey. Is a bson Binary value. -Can be used for ClientEncryption.encrypt, and can be used to directly -query for the data key itself against the key vault namespace.

-
-
ClientEncryptionCreateDataKeyCallback : function
-
-
AWSEncryptionKeyOptions : object
-

Configuration options for making an AWS encryption key

-
-
GCPEncryptionKeyOptions : object
-

Configuration options for making a GCP encryption key

-
-
AzureEncryptionKeyOptions : object
-

Configuration options for making an Azure encryption key

-
-
RewrapManyDataKeyResult : object
-
-
ClientEncryptionEncryptCallback : function
-
-
RangeOptions : object
-

min, max, sparsity, and range must match the values set in the encryptedFields of the destination collection. -For double and decimal128, min/max/precision must all be set, or all be unset.

-
-
EncryptOptions : object
-

Options to provide when encrypting data.

-
-
- - - -## AutoEncrypter -An internal class to be used by the driver for auto encryption -**NOTE**: Not meant to be instantiated directly, this is for internal use only. - - -* [AutoEncrypter](#AutoEncrypter) - - * [new AutoEncrypter(client, [options])](#new_AutoEncrypter_new) - - * _instance_ - * [.cryptSharedLibVersionInfo](#AutoEncrypter+cryptSharedLibVersionInfo) - - * [.askForKMSCredentials()](#AutoEncrypter+askForKMSCredentials) - - * _inner_ - * [~logLevel](#AutoEncrypter..logLevel) - - * [~AutoEncryptionOptions](#AutoEncrypter..AutoEncryptionOptions) - - * [~AutoEncryptionExtraOptions](#AutoEncrypter..AutoEncryptionExtraOptions) - - * [~logger](#AutoEncrypter..logger) - - - - -### new AutoEncrypter(client, [options]) - -| Param | Type | Description | -| --- | --- | --- | -| client | MongoClient | The client autoEncryption is enabled on | -| [options] | [AutoEncryptionOptions](#AutoEncrypter..AutoEncryptionOptions) | Optional settings | - -Create an AutoEncrypter - -**Note**: Do not instantiate this class directly. Rather, supply the relevant options to a MongoClient - -**Note**: Supplying `options.schemaMap` provides more security than relying on JSON Schemas obtained from the server. -It protects against a malicious server advertising a false JSON Schema, which could trick the client into sending unencrypted data that should be encrypted. -Schemas supplied in the schemaMap only apply to configuring automatic encryption for Client-Side Field Level Encryption. -Other validation rules in the JSON schema will not be enforced by the driver and will result in an error. - -**Example** -```js -// Enabling autoEncryption via a MongoClient -const { MongoClient } = require('mongodb'); -const client = new MongoClient(URL, { - autoEncryption: { - kmsProviders: { - aws: { - accessKeyId: AWS_ACCESS_KEY, - secretAccessKey: AWS_SECRET_KEY - } - } - } -}); - -await client.connect(); -// From here on, the client will be encrypting / decrypting automatically -``` - - -### *autoEncrypter*.cryptSharedLibVersionInfo -Return the current libmongocrypt's CSFLE shared library version -as `{ version: bigint, versionStr: string }`, or `null` if no CSFLE -shared library was loaded. - - - -### *autoEncrypter*.askForKMSCredentials() -Ask the user for KMS credentials. - -This returns anything that looks like the kmsProviders original input -option. It can be empty, and any provider specified here will override -the original ones. - - - -### *AutoEncrypter*~logLevel -The level of severity of the log message - -| Value | Level | -|-------|-------| -| 0 | Fatal Error | -| 1 | Error | -| 2 | Warning | -| 3 | Info | -| 4 | Trace | - - - -### *AutoEncrypter*~AutoEncryptionOptions -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| [keyVaultClient] | MongoClient | A `MongoClient` used to fetch keys from a key vault | -| [keyVaultNamespace] | string | The namespace where keys are stored in the key vault | -| [kmsProviders] | [KMSProviders](#KMSProviders) | Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. | -| [schemaMap] | object | A map of namespaces to a local JSON schema for encryption | -| [bypassAutoEncryption] | boolean | Allows the user to bypass auto encryption, maintaining implicit decryption | -| [options.logger] | [logger](#AutoEncrypter..logger) | An optional hook to catch logging messages from the underlying encryption engine | -| [extraOptions] | [AutoEncryptionExtraOptions](#AutoEncrypter..AutoEncryptionExtraOptions) | Extra options related to the mongocryptd process | - -Configuration options for a automatic client encryption. - - - -### *AutoEncrypter*~AutoEncryptionExtraOptions -**Properties** - -| Name | Type | Default | Description | -| --- | --- | --- | --- | -| [mongocryptdURI] | string | | A local process the driver communicates with to determine how to encrypt values in a command. Defaults to "mongodb://%2Fvar%2Fmongocryptd.sock" if domain sockets are available or "mongodb://localhost:27020" otherwise | -| [mongocryptdBypassSpawn] | boolean | false | If true, autoEncryption will not attempt to spawn a mongocryptd before connecting | -| [mongocryptdSpawnPath] | string | | The path to the mongocryptd executable on the system | -| [mongocryptdSpawnArgs] | Array.<string> | | Command line arguments to use when auto-spawning a mongocryptd | - -Extra options related to the mongocryptd process - - - -### *AutoEncrypter*~logger - -| Param | Type | Description | -| --- | --- | --- | -| level | [logLevel](#AutoEncrypter..logLevel) | The level of logging. | -| message | string | The message to log | - -A callback that is invoked with logging information from -the underlying C++ Bindings. - - - -## ClientEncryption -The public interface for explicit in-use encryption - - -* [ClientEncryption](#ClientEncryption) - - * [new ClientEncryption(client, options)](#new_ClientEncryption_new) - - * _instance_ - * [.createDataKey(provider, [options], [callback])](#ClientEncryption+createDataKey) - - * [.rewrapManyDataKey(filter, [options])](#ClientEncryption+rewrapManyDataKey) - - * [.deleteKey(_id)](#ClientEncryption+deleteKey) - - * [.getKeys()](#ClientEncryption+getKeys) - - * [.getKey(_id)](#ClientEncryption+getKey) - - * [.getKeyByAltName(keyAltName)](#ClientEncryption+getKeyByAltName) - - * [.addKeyAltName(_id, keyAltName)](#ClientEncryption+addKeyAltName) - - * [.removeKeyAltName(_id, keyAltName)](#ClientEncryption+removeKeyAltName) - - * [.createEncryptedCollection(db, name, options)](#ClientEncryption+createEncryptedCollection) - - * [.encrypt(value, options, [callback])](#ClientEncryption+encrypt) - - * [.encryptExpression(expression, options)](#ClientEncryption+encryptExpression) - - * [.decrypt(value, callback)](#ClientEncryption+decrypt) - - * [.askForKMSCredentials()](#ClientEncryption+askForKMSCredentials) - - * _inner_ - * [~decryptCallback](#ClientEncryption..decryptCallback) - - - - -### new ClientEncryption(client, options) - -| Param | Type | Description | -| --- | --- | --- | -| client | MongoClient | The client used for encryption | -| options | object | Additional settings | -| options.keyVaultNamespace | string | The namespace of the key vault, used to store encryption keys | -| options.tlsOptions | object | An object that maps KMS provider names to TLS options. | -| [options.keyVaultClient] | MongoClient | A `MongoClient` used to fetch keys from a key vault. Defaults to `client` | -| [options.kmsProviders] | [KMSProviders](#KMSProviders) | options for specific KMS providers to use | - -Create a new encryption instance - -**Example** -```js -new ClientEncryption(mongoClient, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { - local: { - key: masterKey // The master key used for encryption/decryption. A 96-byte long Buffer - } - } -}); -``` -**Example** -```js -new ClientEncryption(mongoClient, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { - aws: { - accessKeyId: AWS_ACCESS_KEY, - secretAccessKey: AWS_SECRET_KEY - } - } -}); -``` - - -### *clientEncryption*.createDataKey(provider, [options], [callback]) - -| Param | Type | Description | -| --- | --- | --- | -| provider | string | The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` | -| [options] | object | Options for creating the data key | -| [options.masterKey] | [AWSEncryptionKeyOptions](#AWSEncryptionKeyOptions) \| [AzureEncryptionKeyOptions](#AzureEncryptionKeyOptions) \| [GCPEncryptionKeyOptions](#GCPEncryptionKeyOptions) | Idenfities a new KMS-specific key used to encrypt the new data key | -| [options.keyAltNames] | Array.<string> | An optional list of string alternate names used to reference a key. If a key is created with alternate names, then encryption may refer to the key by the unique alternate name instead of by _id. | -| [callback] | [ClientEncryptionCreateDataKeyCallback](#ClientEncryptionCreateDataKeyCallback) | Optional callback to invoke when key is created | - -Creates a data key used for explicit encryption and inserts it into the key vault namespace - -**Returns**: Promise \| void - If no callback is provided, returns a Promise that either resolves with [the id of the created data key](ClientEncryption~dataKeyId), or rejects with an error. If a callback is provided, returns nothing. -**Example** -```js -// Using callbacks to create a local key -clientEncryption.createDataKey('local', (err, dataKey) => { - if (err) { - // This means creating the key failed. - } else { - // key creation succeeded - } -}); -``` -**Example** -```js -// Using async/await to create a local key -const dataKeyId = await clientEncryption.createDataKey('local'); -``` -**Example** -```js -// Using async/await to create an aws key -const dataKeyId = await clientEncryption.createDataKey('aws', { - masterKey: { - region: 'us-east-1', - key: 'xxxxxxxxxxxxxx' // CMK ARN here - } -}); -``` -**Example** -```js -// Using async/await to create an aws key with a keyAltName -const dataKeyId = await clientEncryption.createDataKey('aws', { - masterKey: { - region: 'us-east-1', - key: 'xxxxxxxxxxxxxx' // CMK ARN here - }, - keyAltNames: [ 'mySpecialKey' ] -}); -``` - - -### *clientEncryption*.rewrapManyDataKey(filter, [options]) - -| Param | Type | Description | -| --- | --- | --- | -| filter | object | A valid MongoDB filter. Any documents matching this filter will be re-wrapped. | -| [options] | object | | -| options.provider | [KmsProvider](#KmsProvider) | The KMS provider to use when re-wrapping the data keys. | -| [options.masterKey] | [AWSEncryptionKeyOptions](#AWSEncryptionKeyOptions) \| [AzureEncryptionKeyOptions](#AzureEncryptionKeyOptions) \| [GCPEncryptionKeyOptions](#GCPEncryptionKeyOptions) | | - -Searches the keyvault for any data keys matching the provided filter. If there are matches, rewrapManyDataKey then attempts to re-wrap the data keys using the provided options. - -If no matches are found, then no bulk write is performed. - -**Example** -```js -// rewrapping all data data keys (using a filter that matches all documents) -const filter = {}; - -const result = await clientEncryption.rewrapManyDataKey(filter); -if (result.bulkWriteResult != null) { - // keys were re-wrapped, results will be available in the bulkWrite object. -} -``` -**Example** -```js -// attempting to rewrap all data keys with no matches -const filter = { _id: new Binary() } // assume _id matches no documents in the database -const result = await clientEncryption.rewrapManyDataKey(filter); - -if (result.bulkWriteResult == null) { - // no keys matched, `bulkWriteResult` does not exist on the result object -} -``` - - -### *clientEncryption*.deleteKey(_id) - -| Param | Type | Description | -| --- | --- | --- | -| _id | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | the id of the document to delete. | - -Deletes the key with the provided id from the keyvault, if it exists. - -**Returns**: [Promise.<DeleteResult>](#DeleteResult) - Returns a promise that either resolves to a [DeleteResult](#DeleteResult) or rejects with an error. -**Example** -```js -// delete a key by _id -const id = new Binary(); // id is a bson binary subtype 4 object -const { deletedCount } = await clientEncryption.deleteKey(id); - -if (deletedCount != null && deletedCount > 0) { - // successful deletion -} -``` - - -### *clientEncryption*.getKeys() -Finds all the keys currently stored in the keyvault. - -This method will not throw. - -**Returns**: [FindCursor](#FindCursor) - a FindCursor over all keys in the keyvault. -**Example** -```js -// fetching all keys -const keys = await clientEncryption.getKeys().toArray(); -``` - - -### *clientEncryption*.getKey(_id) - -| Param | Type | Description | -| --- | --- | --- | -| _id | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | the id of the document to delete. | - -Finds a key in the keyvault with the specified _id. - -**Returns**: [Promise.<DataKey>](#DataKey) - Returns a promise that either resolves to a [DataKey](#DataKey) if a document matches the key or null if no documents -match the id. The promise rejects with an error if an error is thrown. -**Example** -```js -// getting a key by id -const id = new Binary(); // id is a bson binary subtype 4 object -const key = await clientEncryption.getKey(id); -if (!key) { - // key is null if there was no matching key -} -``` - - -### *clientEncryption*.getKeyByAltName(keyAltName) - -| Param | Type | Description | -| --- | --- | --- | -| keyAltName | string | a keyAltName to search for a key | - -Finds a key in the keyvault which has the specified keyAltName. - -**Returns**: Promise.<(DataKey\|null)> - Returns a promise that either resolves to a [DataKey](#DataKey) if a document matches the key or null if no documents -match the keyAltName. The promise rejects with an error if an error is thrown. -**Example** -```js -// get a key by alt name -const keyAltName = 'keyAltName'; -const key = await clientEncryption.getKeyByAltName(keyAltName); -if (!key) { - // key is null if there is no matching key -} -``` - - -### *clientEncryption*.addKeyAltName(_id, keyAltName) - -| Param | Type | Description | -| --- | --- | --- | -| _id | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | The id of the document to update. | -| keyAltName | string | a keyAltName to search for a key | - -Adds a keyAltName to a key identified by the provided _id. - -This method resolves to/returns the *old* key value (prior to adding the new altKeyName). - -**Returns**: [Promise.<DataKey>](#DataKey) - Returns a promise that either resolves to a [DataKey](#DataKey) if a document matches the key or null if no documents -match the id. The promise rejects with an error if an error is thrown. -**Example** -```js -// adding an keyAltName to a data key -const id = new Binary(); // id is a bson binary subtype 4 object -const keyAltName = 'keyAltName'; -const oldKey = await clientEncryption.addKeyAltName(id, keyAltName); -if (!oldKey) { - // null is returned if there is no matching document with an id matching the supplied id -} -``` - - -### *clientEncryption*.removeKeyAltName(_id, keyAltName) - -| Param | Type | Description | -| --- | --- | --- | -| _id | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | The id of the document to update. | -| keyAltName | string | a keyAltName to search for a key | - -Adds a keyAltName to a key identified by the provided _id. - -This method resolves to/returns the *old* key value (prior to removing the new altKeyName). - -If the removed keyAltName is the last keyAltName for that key, the `altKeyNames` property is unset from the document. - -**Returns**: Promise.<(DataKey\|null)> - Returns a promise that either resolves to a [DataKey](#DataKey) if a document matches the key or null if no documents -match the id. The promise rejects with an error if an error is thrown. -**Example** -```js -// removing a key alt name from a data key -const id = new Binary(); // id is a bson binary subtype 4 object -const keyAltName = 'keyAltName'; -const oldKey = await clientEncryption.removeKeyAltName(id, keyAltName); - -if (!oldKey) { - // null is returned if there is no matching document with an id matching the supplied id -} -``` - - -### *clientEncryption*.createEncryptedCollection(db, name, options) -**Throws**: - -- [MongoCryptCreateDataKeyError](#MongoCryptCreateDataKeyError) - If part way through the process a createDataKey invocation fails, an error will be rejected that has the partial `encryptedFields` that were created. -- [MongoCryptCreateEncryptedCollectionError](#MongoCryptCreateEncryptedCollectionError) - If creating the collection fails, an error will be rejected that has the entire `encryptedFields` that were created. - -**Experimental**: Public Technical Preview - -A convenience method for creating an encrypted collection. -This method will create data keys for any encryptedFields that do not have a `keyId` defined -and then create a new collection with the full set of encryptedFields. - -| Param | Type | Description | -| --- | --- | --- | -| db | Db | A Node.js driver Db object with which to create the collection | -| name | string | The name of the collection to be created | -| options | object | Options for createDataKey and for createCollection | -| options.provider | string | KMS provider name | -| [options.masterKey] | [AWSEncryptionKeyOptions](#AWSEncryptionKeyOptions) \| [AzureEncryptionKeyOptions](#AzureEncryptionKeyOptions) \| [GCPEncryptionKeyOptions](#GCPEncryptionKeyOptions) | masterKey to pass to createDataKey | -| options.createCollectionOptions | CreateCollectionOptions | options to pass to createCollection, must include `encryptedFields` | - -**Returns**: Promise.<{collection: Collection.<TSchema>, encryptedFields: Document}> - - created collection and generated encryptedFields - - -### *clientEncryption*.encrypt(value, options, [callback]) - -| Param | Type | Description | -| --- | --- | --- | -| value | \* | The value that you wish to serialize. Must be of a type that can be serialized into BSON | -| options | [EncryptOptions](#EncryptOptions) | | -| [callback] | [ClientEncryptionEncryptCallback](#ClientEncryptionEncryptCallback) | Optional callback to invoke when value is encrypted | - -Explicitly encrypt a provided value. Note that either `options.keyId` or `options.keyAltName` must -be specified. Specifying both `options.keyId` and `options.keyAltName` is considered an error. - -**Returns**: Promise \| void - If no callback is provided, returns a Promise that either resolves with the encrypted value, or rejects with an error. If a callback is provided, returns nothing. -**Example** -```js -// Encryption with callback API -function encryptMyData(value, callback) { - clientEncryption.createDataKey('local', (err, keyId) => { - if (err) { - return callback(err); - } - clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }, callback); - }); -} -``` -**Example** -```js -// Encryption with async/await api -async function encryptMyData(value) { - const keyId = await clientEncryption.createDataKey('local'); - return clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }); -} -``` -**Example** -```js -// Encryption using a keyAltName -async function encryptMyData(value) { - await clientEncryption.createDataKey('local', { keyAltNames: 'mySpecialKey' }); - return clientEncryption.encrypt(value, { keyAltName: 'mySpecialKey', algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }); -} -``` - - -### *clientEncryption*.encryptExpression(expression, options) -**Experimental**: The Range algorithm is experimental only. It is not intended for production use. It is subject to breaking changes. - -| Param | Type | Description | -| --- | --- | --- | -| expression | object | a BSON document of one of the following forms: 1. A Match Expression of this form: `{$and: [{: {$gt: }}, {: {$lt: }}]}` 2. An Aggregate Expression of this form: `{$and: [{$gt: [, ]}, {$lt: [, ]}]}` `$gt` may also be `$gte`. `$lt` may also be `$lte`. | -| options | [EncryptOptions](#EncryptOptions) | | - -Encrypts a Match Expression or Aggregate Expression to query a range index. - -Only supported when queryType is "rangePreview" and algorithm is "RangePreview". - -**Returns**: Promise.<object> - Returns a Promise that either resolves with the encrypted value or rejects with an error. - - -### *clientEncryption*.decrypt(value, callback) - -| Param | Type | Description | -| --- | --- | --- | -| value | Buffer \| Binary | An encrypted value | -| callback | [decryptCallback](#ClientEncryption..decryptCallback) | Optional callback to invoke when value is decrypted | - -Explicitly decrypt a provided encrypted value - -**Returns**: Promise \| void - If no callback is provided, returns a Promise that either resolves with the decrypted value, or rejects with an error. If a callback is provided, returns nothing. -**Example** -```js -// Decrypting value with callback API -function decryptMyValue(value, callback) { - clientEncryption.decrypt(value, callback); -} -``` -**Example** -```js -// Decrypting value with async/await API -async function decryptMyValue(value) { - return clientEncryption.decrypt(value); -} -``` - - -### *clientEncryption*.askForKMSCredentials() -Ask the user for KMS credentials. - -This returns anything that looks like the kmsProviders original input -option. It can be empty, and any provider specified here will override -the original ones. - - - -### *ClientEncryption*~decryptCallback - -| Param | Type | Description | -| --- | --- | --- | -| [err] | Error | If present, indicates an error that occurred in the process of decryption | -| [result] | object | If present, is the decrypted result | - - - -## MongoCryptError -An error indicating that something went wrong specifically with MongoDB Client Encryption - - - -## MongoCryptCreateDataKeyError -**Experimental**: Public Technical Preview -An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create data keys - - - -## MongoCryptCreateEncryptedCollectionError -**Experimental**: Public Technical Preview -An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create a collection - - - -## MongoCryptAzureKMSRequestError -An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials. - - - -### new MongoCryptAzureKMSRequestError(message, body) - -| Param | Type | -| --- | --- | -| message | string | -| body | object \| undefined | - - - -## BSONValue -any serializable BSON value - - - -## Long -A 64 bit integer, represented by the js-bson Long type. - - - -## KMSProviders -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| [aws] | object | Configuration options for using 'aws' as your KMS provider | -| [aws.accessKeyId] | string | The access key used for the AWS KMS provider | -| [aws.secretAccessKey] | string | The secret access key used for the AWS KMS provider | -| [local] | object | Configuration options for using 'local' as your KMS provider | -| [local.key] | Buffer | The master key used to encrypt/decrypt data keys. A 96-byte long Buffer. | -| [azure] | object | Configuration options for using 'azure' as your KMS provider | -| [azure.tenantId] | string | The tenant ID identifies the organization for the account | -| [azure.clientId] | string | The client ID to authenticate a registered application | -| [azure.clientSecret] | string | The client secret to authenticate a registered application | -| [azure.identityPlatformEndpoint] | string | If present, a host with optional port. E.g. "example.com" or "example.com:443". This is optional, and only needed if customer is using a non-commercial Azure instance (e.g. a government or China account, which use different URLs). Defaults to "login.microsoftonline.com" | -| [gcp] | object | Configuration options for using 'gcp' as your KMS provider | -| [gcp.email] | string | The service account email to authenticate | -| [gcp.privateKey] | string \| Binary | A PKCS#8 encrypted key. This can either be a base64 string or a binary representation | -| [gcp.endpoint] | string | If present, a host with optional port. E.g. "example.com" or "example.com:443". Defaults to "oauth2.googleapis.com" | - -Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. - - - -## DataKey -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| _id | UUID | A unique identifier for the key. | -| version | number | A numeric identifier for the schema version of this document. Implicitly 0 if unset. | -| [keyAltNames] | Array.<string> | Alternate names to search for keys by. Used for a per-document key scenario in support of GDPR scenarios. | -| keyMaterial | Binary | Encrypted data key material, BinData type General. | -| creationDate | Date | The datetime the wrapped data key material was imported into the Key Database. | -| updateDate | Date | The datetime the wrapped data key material was last modified. On initial import, this value will be set to creationDate. | -| status | number | 0 = enabled, 1 = disabled | -| masterKey | object | the encrypted master key | - -A data key as stored in the database. - - - -## KmsProvider -A string containing the name of a kms provider. Valid options are 'aws', 'azure', 'gcp', 'kmip', or 'local' - - - -## ClientSession -The ClientSession class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/ClientSession.html) - - - -## DeleteResult -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| acknowledged | boolean | Indicates whether this write result was acknowledged. If not, then all other members of this result will be undefined. | -| deletedCount | number | The number of documents that were deleted | - -The result of a delete operation from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/interfaces/DeleteResult.html) - - - -## BulkWriteResult -The BulkWriteResult class from the MongoDB Node driver (https://mongodb.github.io/node-mongodb-native/4.8/classes/BulkWriteResult.html) - - - -## FindCursor -The FindCursor class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/FindCursor.html) - - - -## ClientEncryptionDataKeyId -The id of an existing dataKey. Is a bson Binary value. -Can be used for [ClientEncryption.encrypt](ClientEncryption.encrypt), and can be used to directly -query for the data key itself against the key vault namespace. - - - -## ClientEncryptionCreateDataKeyCallback - -| Param | Type | Description | -| --- | --- | --- | -| [error] | Error | If present, indicates an error that occurred in the creation of the data key | -| [dataKeyId] | ClientEncryption~dataKeyId | If present, returns the id of the created data key | - - - -## AWSEncryptionKeyOptions -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| region | string | The AWS region of the KMS | -| key | string | The Amazon Resource Name (ARN) to the AWS customer master key (CMK) | -| [endpoint] | string | An alternate host to send KMS requests to. May include port number | - -Configuration options for making an AWS encryption key - - - -## GCPEncryptionKeyOptions -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| projectId | string | GCP project id | -| location | string | Location name (e.g. "global") | -| keyRing | string | Key ring name | -| keyName | string | Key name | -| [keyVersion] | string | Key version | -| [endpoint] | string | KMS URL, defaults to `https://www.googleapis.com/auth/cloudkms` | - -Configuration options for making a GCP encryption key - - - -## AzureEncryptionKeyOptions -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| keyName | string | Key name | -| keyVaultEndpoint | string | Key vault URL, typically `.vault.azure.net` | -| [keyVersion] | string | Key version | - -Configuration options for making an Azure encryption key - - - -## RewrapManyDataKeyResult -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| [bulkWriteResult] | [BulkWriteResult](#BulkWriteResult) | An optional BulkWriteResult, if any keys were matched and attempted to be re-wrapped. | - - - -## ClientEncryptionEncryptCallback - -| Param | Type | Description | -| --- | --- | --- | -| [err] | Error | If present, indicates an error that occurred in the process of encryption | -| [result] | Buffer | If present, is the encrypted result | - - - -## RangeOptions -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| min | [BSONValue](#BSONValue) | is required if precision is set. | -| max | [BSONValue](#BSONValue) | is required if precision is set. | -| sparsity | BSON.Long | | -| precision | number \| undefined | (may only be set for double or decimal128). | - -min, max, sparsity, and range must match the values set in the encryptedFields of the destination collection. -For double and decimal128, min/max/precision must all be set, or all be unset. - - - -## EncryptOptions -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| [keyId] | [ClientEncryptionDataKeyId](#ClientEncryptionDataKeyId) | The id of the Binary dataKey to use for encryption. | -| [keyAltName] | string | A unique string name corresponding to an already existing dataKey. | -| [algorithm] | string | The algorithm to use for encryption. Must be either `'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'`, `'AEAD_AES_256_CBC_HMAC_SHA_512-Random'`, `'Indexed'` or `'Unindexed'` | -| [contentionFactor] | bigint \| number | (experimental) - the contention factor. | -| queryType | 'equality' \| 'rangePreview' | (experimental) - the query type supported. | -| [rangeOptions] | [RangeOptions](#RangeOptions) | (experimental) The index options for a Queryable Encryption field supporting "rangePreview" queries. | - -Options to provide when encrypting data. +#### https://github.com/mongodb-js/mongodb-client-encryption +They can still be found at the same npm package: +- https://www.npmjs.com/package/mongodb-client-encryption diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/binding.gyp b/ext/libmongocrypt/libmongocrypt/bindings/node/binding.gyp deleted file mode 100644 index 0d85e7a..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/binding.gyp +++ /dev/null @@ -1,79 +0,0 @@ -{ - 'targets': [{ - 'target_name': 'mongocrypt', - 'include_dirs': [ - "main}} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/etc/build-static.sh b/ext/libmongocrypt/libmongocrypt/bindings/node/etc/build-static.sh deleted file mode 100755 index 1557085..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/etc/build-static.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit - -THIS_DIR="$(dirname "${BASH_SOURCE[0]}")" -. "$THIS_DIR/../../../.evergreen/init.sh" - -NODE_DIR="$(abspath "$THIS_DIR/..")" - -DEPS_PREFIX="$NODE_DIR/deps" -BUILD_DIR=$DEPS_PREFIX/tmp -: "${CMAKE_FLAGS:=}" -: "${WINDOWS_CMAKE_FLAGS:=}" - -# build and install libmongocrypt -mkdir -p $BUILD_DIR/libmongocrypt-build -pushd $BUILD_DIR/libmongocrypt-build #./deps/tmp/libmongocrypt-build - -CMAKE_FLAGS="-DDISABLE_NATIVE_CRYPTO=1 -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_MORE_WARNINGS_AS_ERRORS=ON" -if [ "$OS_NAME" == "windows" ]; then - if [ "${WINDOWS_32BIT-}" != "ON" ]; then - WINDOWS_CMAKE_FLAGS="-Thost=x64 -A x64 -DENABLE_WINDOWS_STATIC_RUNTIME=ON" - else - WINDOWS_CMAKE_FLAGS="-DENABLE_WINDOWS_STATIC_RUNTIME=ON" - fi - run_cmake $CMAKE_FLAGS $WINDOWS_CMAKE_FLAGS -DCMAKE_PREFIX_PATH="$(native_path "$DEPS_PREFIX")" -DCMAKE_INSTALL_PREFIX="$(native_path "$DEPS_PREFIX")" "$(native_path "$LIBMONGOCRYPT_DIR")" -else - run_cmake $CMAKE_FLAGS -DCMAKE_PREFIX_PATH=$DEPS_PREFIX -DCMAKE_INSTALL_PREFIX=$DEPS_PREFIX -DCMAKE_OSX_DEPLOYMENT_TARGET="10.12" $LIBMONGOCRYPT_DIR -fi - -run_cmake --build . --target install --config RelWithDebInfo - -popd #./ - -# build the `mongodb-client-encryption` addon -env BUILD_TYPE=static npm install diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/index.d.ts b/ext/libmongocrypt/libmongocrypt/bindings/node/index.d.ts deleted file mode 100644 index f831a20..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/index.d.ts +++ /dev/null @@ -1,641 +0,0 @@ -import type { - MongoClient, - BulkWriteResult, - DeleteResult, - FindCursor, - Collection, - Db, - CreateCollectionOptions, - Document, - Binary, - Long -} from 'mongodb'; - -export type ClientEncryptionDataKeyProvider = 'aws' | 'azure' | 'gcp' | 'local' | 'kmip'; - -/** - * The schema for a DataKey in the key vault collection. - */ -export interface DataKey { - _id: Binary; - version?: number; - keyAltNames?: string[]; - keyMaterial: Binary; - creationDate: Date; - updateDate: Date; - status: number; - masterKey: Document; -} - -/** - * An error indicating that something went wrong specifically with MongoDB Client Encryption - */ -export class MongoCryptError extends Error { - cause?: Error; -} - -/** - * @experimental Public Technical Preview - * An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create a collection - */ -export class MongoCryptCreateEncryptedCollectionError extends MongoCryptError { - /** - * @experimental Public Technical Preview - * The entire `encryptedFields` that was completed while attempting createEncryptedCollection - */ - encryptedFields: Document; - /** The error rejected from db.createCollection() */ - cause: Error; -} - -/** - * @experimental Public Technical Preview - * An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create data keys - */ -export class MongoCryptCreateDataKeyError extends MongoCryptError { - /** - * @experimental Public Technical Preview - * The partial `encryptedFields` that was completed while attempting createEncryptedCollection - */ - encryptedFields: Document; - /** The first error encountered when attempting to `createDataKey` */ - cause: Error; -} - -/** - * An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials. - */ -export class MongoCryptAzureKMSRequestError extends MongoCryptError { - /* The body of the IMDS request that produced the error, if present. */ - body?: Document ; -} - -export class MongoCryptKMSRequestNetworkTimeoutError extends MongoCryptError {} - -/** - * A set of options for specifying a Socks5 proxy. - */ -export interface ProxyOptions { - proxyHost: string; - proxyPort?: number; - proxyUsername?: string; - proxyPassword?: string; -} - -export interface ClientEncryptionCreateDataKeyCallback { - /** - * @param error If present, indicates an error that occurred in the creation of the data key - * @param dataKeyId If present, returns the id of the created data key - */ - (error?: Error, dataKeyId?: Binary): void; -} - -export interface ClientEncryptionEncryptCallback { - /** - * @param error If present, indicates an error that occurred in the process of encryption - * @param result If present, is the encrypted result - */ - (error?: Error, result?: Binary): void; -} - -export interface ClientEncryptionDecryptCallback { - /** - * @param error If present, indicates an error that occurred in the process of decryption - * @param result If present, is the decrypted result - */ - (error?: Error, result?: any): void; -} - -/** - * Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. - */ -export interface KMSProviders { - /** - * Configuration options for using 'aws' as your KMS provider - */ - aws?: - | { - /** - * The access key used for the AWS KMS provider - */ - accessKeyId: string; - - /** - * The secret access key used for the AWS KMS provider - */ - secretAccessKey: string; - - /** - * An optional AWS session token that will be used as the - * X-Amz-Security-Token header for AWS requests. - */ - sessionToken?: string; - } - | Record; - - /** - * Configuration options for using 'local' as your KMS provider - */ - local?: { - /** - * The master key used to encrypt/decrypt data keys. - * A 96-byte long Buffer or base64 encoded string. - */ - key: Buffer | string; - }; - - /** - * Configuration options for using 'kmip' as your KMS provider - */ - kmip?: { - /** - * The output endpoint string. - * The endpoint consists of a hostname and port separated by a colon. - * E.g. "example.com:123". A port is always present. - */ - endpoint?: string; - }; - - /** - * Configuration options for using 'azure' as your KMS provider - */ - azure?: - | { - /** - * The tenant ID identifies the organization for the account - */ - tenantId: string; - - /** - * The client ID to authenticate a registered application - */ - clientId: string; - - /** - * The client secret to authenticate a registered application - */ - clientSecret: string; - - /** - * If present, a host with optional port. E.g. "example.com" or "example.com:443". - * This is optional, and only needed if customer is using a non-commercial Azure instance - * (e.g. a government or China account, which use different URLs). - * Defaults to "login.microsoftonline.com" - */ - identityPlatformEndpoint?: string | undefined; - } - | { - /** - * If present, an access token to authenticate with Azure. - */ - accessToken: string; - } - | Record; - - /** - * Configuration options for using 'gcp' as your KMS provider - */ - gcp?: - | { - /** - * The service account email to authenticate - */ - email: string; - - /** - * A PKCS#8 encrypted key. This can either be a base64 string or a binary representation - */ - privateKey: string | Buffer; - - /** - * If present, a host with optional port. E.g. "example.com" or "example.com:443". - * Defaults to "oauth2.googleapis.com" - */ - endpoint?: string | undefined; - } - | { - /** - * If present, an access token to authenticate with GCP. - */ - accessToken: string; - } - | Record; -} - -/** - * TLS options to use when connecting. The spec specifically calls out which insecure - * tls options are not allowed: - * - * - tlsAllowInvalidCertificates - * - tlsAllowInvalidHostnames - * - tlsInsecure - * - tlsDisableOCSPEndpointCheck - * - tlsDisableCertificateRevocationCheck - */ -export interface ClientEncryptionTlsOptions { - /** - * Specifies the location of a local .pem file that contains - * either the client's TLS/SSL certificate and key or only the - * client's TLS/SSL key when tlsCertificateFile is used to - * provide the certificate. - */ - tlsCertificateKeyFile?: string; - /** - * Specifies the password to de-crypt the tlsCertificateKeyFile. - */ - tlsCertificateKeyFilePassword?: string; - /** - * Specifies the location of a local .pem file that contains the - * root certificate chain from the Certificate Authority. - * This file is used to validate the certificate presented by the - * KMS provider. - */ - tlsCAFile?: string; -} - -/** - * Additional settings to provide when creating a new `ClientEncryption` instance. - */ -export interface ClientEncryptionOptions { - /** - * The namespace of the key vault, used to store encryption keys - */ - keyVaultNamespace: string; - - /** - * A MongoClient used to fetch keys from a key vault. Defaults to client. - */ - keyVaultClient?: MongoClient | undefined; - - /** - * Options for specific KMS providers to use - */ - kmsProviders?: KMSProviders; - - /** - * Optional callback to override KMS providers per-context. - * - * @deprecated Installing optional dependencies will automatically refresh kms - * provider credentials. - */ - onKmsProviderRefresh?: () => Promise; - - /** - * Options for specifying a Socks5 proxy to use for connecting to the KMS. - */ - proxyOptions?: ProxyOptions; - - /** - * TLS options for kms providers to use. - */ - tlsOptions?: { [kms in keyof KMSProviders]?: ClientEncryptionTlsOptions }; -} - -/** - * Configuration options for making an AWS encryption key - */ -export interface AWSEncryptionKeyOptions { - /** - * The AWS region of the KMS - */ - region: string; - - /** - * The Amazon Resource Name (ARN) to the AWS customer master key (CMK) - */ - key: string; - - /** - * An alternate host to send KMS requests to. May include port number. - */ - endpoint?: string | undefined; -} - -/** - * Configuration options for making an AWS encryption key - */ -export interface GCPEncryptionKeyOptions { - /** - * GCP project ID - */ - projectId: string; - - /** - * Location name (e.g. "global") - */ - location: string; - - /** - * Key ring name - */ - keyRing: string; - - /** - * Key name - */ - keyName: string; - - /** - * Key version - */ - keyVersion?: string | undefined; - - /** - * KMS URL, defaults to `https://www.googleapis.com/auth/cloudkms` - */ - endpoint?: string | undefined; -} - -/** - * Configuration options for making an Azure encryption key - */ -export interface AzureEncryptionKeyOptions { - /** - * Key name - */ - keyName: string; - - /** - * Key vault URL, typically `.vault.azure.net` - */ - keyVaultEndpoint: string; - - /** - * Key version - */ - keyVersion?: string | undefined; -} - -/** - * Options to provide when creating a new data key. - */ -export interface ClientEncryptionCreateDataKeyProviderOptions { - /** - * Identifies a new KMS-specific key used to encrypt the new data key - */ - masterKey?: - | AWSEncryptionKeyOptions - | AzureEncryptionKeyOptions - | GCPEncryptionKeyOptions - | undefined; - - /** - * An optional list of string alternate names used to reference a key. - * If a key is created with alternate names, then encryption may refer to the key by the unique alternate name instead of by _id. - */ - keyAltNames?: string[] | undefined; - - /** @experimental */ - keyMaterial?: Buffer | Binary; -} - -/** @experimental */ -export interface ClientEncryptionRewrapManyDataKeyProviderOptions { - provider: ClientEncryptionDataKeyProvider; - masterKey?: - | AWSEncryptionKeyOptions - | AzureEncryptionKeyOptions - | GCPEncryptionKeyOptions - | undefined; -} - -/** @experimental */ -export interface ClientEncryptionRewrapManyDataKeyResult { - /** The result of rewrapping data keys. If unset, no keys matched the filter. */ - bulkWriteResult?: BulkWriteResult; -} - -/** - * RangeOptions specifies index options for a Queryable Encryption field supporting "rangePreview" queries. - * min, max, sparsity, and range must match the values set in the encryptedFields of the destination collection. - * For double and decimal128, min/max/precision must all be set, or all be unset. - */ -interface RangeOptions { - min?: any; - max?: any; - sparsity: Long; - precision?: number; -} - -/** - * Options to provide when encrypting data. - */ -export interface ClientEncryptionEncryptOptions { - /** - * The algorithm to use for encryption. - */ - algorithm: - | 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' - | 'AEAD_AES_256_CBC_HMAC_SHA_512-Random' - | 'Indexed' - | 'Unindexed' - | 'RangePreview'; - - /** - * The id of the Binary dataKey to use for encryption - */ - keyId?: Binary; - - /** - * A unique string name corresponding to an already existing dataKey. - */ - keyAltName?: string; - - /** @experimental Public Technical Preview: The contention factor. */ - contentionFactor?: bigint | number; - - /** @experimental Public Technical Preview: The query type supported */ - queryType?: 'equality' | 'rangePreview'; - - /** @experimental Public Technical Preview: The index options for a Queryable Encryption field supporting "rangePreview" queries.*/ - rangeOptions?: RangeOptions; -} - -/** - * The public interface for explicit in-use encryption - */ -export class ClientEncryption { - /** - * Create a new encryption instance. - * @param client The client used for encryption - * @param options Additional settings - */ - constructor(client: MongoClient, options: ClientEncryptionOptions); - - /** - * Creates a data key used for explicit encryption and inserts it into the key vault namespace - * @param provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` - */ - createDataKey(provider: ClientEncryptionDataKeyProvider): Promise; - - /** - * Creates a data key used for explicit encryption and inserts it into the key vault namespace - * @param provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` - * @param options Options for creating the data key - */ - createDataKey( - provider: ClientEncryptionDataKeyProvider, - options: ClientEncryptionCreateDataKeyProviderOptions - ): Promise; - - /** - * Creates a data key used for explicit encryption and inserts it into the key vault namespace - * @param provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` - * @param callback Callback to invoke when key is created - */ - createDataKey( - provider: ClientEncryptionDataKeyProvider, - callback: ClientEncryptionCreateDataKeyCallback - ): void; - - /** - * Creates a data key used for explicit encryption and inserts it into the key vault namespace - * @param provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` - * @param options Options for creating the data key - * @param callback Callback to invoke when key is created - */ - createDataKey( - provider: ClientEncryptionDataKeyProvider, - options: ClientEncryptionCreateDataKeyProviderOptions, - callback: ClientEncryptionCreateDataKeyCallback - ): void; - - /** - * Searches the keyvault for any data keys matching the provided filter. If there are matches, rewrapManyDataKey then attempts to re-wrap the data keys using the provided options. - * - * If no matches are found, then no bulk write is performed. - */ - rewrapManyDataKey( - filter: Document, - options?: ClientEncryptionRewrapManyDataKeyProviderOptions - ): Promise; - - /** - * Deletes the key with the provided id from the keyvault, if it exists. - * - * @param id - the id of the document to delete. - */ - deleteKey(id: Binary): Promise; - - /** - * Finds all the keys currently stored in the keyvault. - * - * This method will not throw. - */ - getKeys(): FindCursor; - - /** - * Finds a key in the keyvault with the specified key. - * - * @param id - the id of the document to delete. - */ - getKey(id: Binary): Promise; - - /** - * Finds a key in the keyvault which has the specified keyAltNames as a keyAltName. - * - * @param keyAltName - a potential keyAltName to search for in the keyAltNames array - */ - getKeyByAltName(keyAltName: string): Promise; - - /** - * Adds a keyAltName to a key identified by the provided `id`. - * - * This method resolves to/returns the *old* key value (prior to adding the new altKeyName). - * - * @param id - The id of the document to update. - * @param keyAltName - a keyAltName to search for a key - */ - addKeyAltName(id: Binary, keyAltName: string): Promise; - - /** - * Adds a keyAltName to a key identified by the provided `id`. - * - * This method resolves to/returns the *old* key value (prior to removing the new altKeyName). - * - * If the removed keyAltName is the last keyAltName for that key, the `altKeyNames` property is unset from the document. - * - * @param id - the id of the document to update. - * @param keyAltName - a keyAltName to search for a key - */ - removeKeyAltName(id: Binary, keyAltName: string): Promise; - - /** - * @experimental Public Technical Preview - * A convenience method for creating an encrypted collection. - * This method will create data keys for any encryptedFields that do not have a `keyId` defined - * and then create a new collection with the full set of encryptedFields. - * - * @param db - A Node.js driver Db object with which to create the collection - * @param name - The name of the new collection - * @param options - Options for createDataKey and for createCollection. A provider and partially created encryptedFields **must** be provided. - * @throws {MongoCryptCreateDataKeyForEncryptedCollectionError} - If part way through the process a createDataKey invocation fails, an error will be rejected that has the partial `encryptedFields` that were created. - * @throws {MongoCryptCreateEncryptedCollectionError} - If creating the collection fails, an error will be rejected that has the entire `encryptedFields` that were created. - */ - createEncryptedCollection( - db: Db, - name: string, - options: { - provider: ClientEncryptionDataKeyProvider; - createCollectionOptions: Omit & { - encryptedFields: Document; - }; - masterKey?: AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions; - } - ): Promise<{ collection: Collection; encryptedFields: Document }>; - - /** - * Explicitly encrypt a provided value. - * Note that either options.keyId or options.keyAltName must be specified. - * Specifying both options.keyId and options.keyAltName is considered an error. - * @param value The value that you wish to serialize. Must be of a type that can be serialized into BSON - * @param options - */ - encrypt(value: any, options: ClientEncryptionEncryptOptions): Promise; - - /** - * Explicitly encrypt a provided value. - * Note that either options.keyId or options.keyAltName must be specified. - * Specifying both options.keyId and options.keyAltName is considered an error. - * @param value The value that you wish to serialize. Must be of a type that can be serialized into BSON - * @param options - * @param callback Callback to invoke when value is encrypted - */ - encrypt( - value: any, - options: ClientEncryptionEncryptOptions, - callback: ClientEncryptionEncryptCallback - ): void; - - /** - * Encrypts a Match Expression or Aggregate Expression to query a range index. - * - * Only supported when queryType is "rangePreview" and algorithm is "RangePreview". - * - * @experimental The Range algorithm is experimental only. It is not intended for production use. It is subject to breaking changes.The aggregation or match expression you wish to encrypt. The value must be in the form - * - * The expression to encrypt must be one of the following: - * 1. A Match Expression of this form: - * `{$and: [{: {$gt: }}, {: {$lt: }}]}` - * 2. An Aggregate Expression of this form: - * `{$and: [{$gt: [, ]}, {$lt: [, ]}]}` - * - * `$gt` may also be `$gte`. `$lt` may also be `$lte`. - */ - encryptExpression(value: Document, options: ClientEncryptionEncryptOptions): Promise; - - /** - * Explicitly decrypt a provided encrypted value - * @param value An encrypted value - */ - decrypt(value: Buffer | Binary): Promise; - - /** - * Explicitly decrypt a provided encrypted value - * @param value An encrypted value - * @param callback Callback to invoke when value is decrypted - */ - decrypt(value: Buffer | Binary, callback: ClientEncryptionDecryptCallback): void; - - static readonly libmongocryptVersion: string; -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/autoEncrypter.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/autoEncrypter.js deleted file mode 100644 index 069cf06..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/autoEncrypter.js +++ /dev/null @@ -1,420 +0,0 @@ -'use strict'; - -module.exports = function (modules) { - const mc = require('bindings')('mongocrypt'); - const common = require('./common'); - const databaseNamespace = common.databaseNamespace; - const StateMachine = modules.stateMachine.StateMachine; - const MongocryptdManager = require('./mongocryptdManager').MongocryptdManager; - const MongoClient = modules.mongodb.MongoClient; - const MongoError = modules.mongodb.MongoError; - const BSON = modules.mongodb.BSON; - const { loadCredentials } = require('./providers/index'); - const cryptoCallbacks = require('./cryptoCallbacks'); - - /** - * Configuration options for a automatic client encryption. - * - * @typedef {Object} AutoEncrypter~AutoEncryptionOptions - * @property {MongoClient} [keyVaultClient] A `MongoClient` used to fetch keys from a key vault - * @property {string} [keyVaultNamespace] The namespace where keys are stored in the key vault - * @property {KMSProviders} [kmsProviders] Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. - * @property {object} [schemaMap] A map of namespaces to a local JSON schema for encryption - * @property {boolean} [bypassAutoEncryption] Allows the user to bypass auto encryption, maintaining implicit decryption - * @property {AutoEncrypter~logger} [options.logger] An optional hook to catch logging messages from the underlying encryption engine - * @property {AutoEncrypter~AutoEncryptionExtraOptions} [extraOptions] Extra options related to the mongocryptd process - */ - - /** - * Extra options related to the mongocryptd process - * @typedef {object} AutoEncrypter~AutoEncryptionExtraOptions - * @property {string} [mongocryptdURI] A local process the driver communicates with to determine how to encrypt values in a command. Defaults to "mongodb://%2Fvar%2Fmongocryptd.sock" if domain sockets are available or "mongodb://localhost:27020" otherwise - * @property {boolean} [mongocryptdBypassSpawn=false] If true, autoEncryption will not attempt to spawn a mongocryptd before connecting - * @property {string} [mongocryptdSpawnPath] The path to the mongocryptd executable on the system - * @property {string[]} [mongocryptdSpawnArgs] Command line arguments to use when auto-spawning a mongocryptd - */ - - /** - * @callback AutoEncrypter~logger - * @description A callback that is invoked with logging information from - * the underlying C++ Bindings. - * @param {AutoEncrypter~logLevel} level The level of logging. - * @param {string} message The message to log - */ - - /** - * @name AutoEncrypter~logLevel - * @enum {number} - * @description - * The level of severity of the log message - * - * | Value | Level | - * |-------|-------| - * | 0 | Fatal Error | - * | 1 | Error | - * | 2 | Warning | - * | 3 | Info | - * | 4 | Trace | - */ - - /** - * @classdesc An internal class to be used by the driver for auto encryption - * **NOTE**: Not meant to be instantiated directly, this is for internal use only. - */ - class AutoEncrypter { - /** - * Create an AutoEncrypter - * - * **Note**: Do not instantiate this class directly. Rather, supply the relevant options to a MongoClient - * - * **Note**: Supplying `options.schemaMap` provides more security than relying on JSON Schemas obtained from the server. - * It protects against a malicious server advertising a false JSON Schema, which could trick the client into sending unencrypted data that should be encrypted. - * Schemas supplied in the schemaMap only apply to configuring automatic encryption for Client-Side Field Level Encryption. - * Other validation rules in the JSON schema will not be enforced by the driver and will result in an error. - * @param {MongoClient} client The client autoEncryption is enabled on - * @param {AutoEncrypter~AutoEncryptionOptions} [options] Optional settings - * - * @example - * // Enabling autoEncryption via a MongoClient - * const { MongoClient } = require('mongodb'); - * const client = new MongoClient(URL, { - * autoEncryption: { - * kmsProviders: { - * aws: { - * accessKeyId: AWS_ACCESS_KEY, - * secretAccessKey: AWS_SECRET_KEY - * } - * } - * } - * }); - * - * await client.connect(); - * // From here on, the client will be encrypting / decrypting automatically - */ - constructor(client, options) { - this._client = client; - this._bson = options.bson || BSON || client.topology.bson; - this._bypassEncryption = options.bypassAutoEncryption === true; - - this._keyVaultNamespace = options.keyVaultNamespace || 'admin.datakeys'; - this._keyVaultClient = options.keyVaultClient || client; - this._metaDataClient = options.metadataClient || client; - this._proxyOptions = options.proxyOptions || {}; - this._tlsOptions = options.tlsOptions || {}; - this._onKmsProviderRefresh = options.onKmsProviderRefresh; - this._kmsProviders = options.kmsProviders || {}; - - const mongoCryptOptions = {}; - if (options.schemaMap) { - mongoCryptOptions.schemaMap = Buffer.isBuffer(options.schemaMap) - ? options.schemaMap - : this._bson.serialize(options.schemaMap); - } - - if (options.encryptedFieldsMap) { - mongoCryptOptions.encryptedFieldsMap = Buffer.isBuffer(options.encryptedFieldsMap) - ? options.encryptedFieldsMap - : this._bson.serialize(options.encryptedFieldsMap); - } - - mongoCryptOptions.kmsProviders = !Buffer.isBuffer(this._kmsProviders) - ? this._bson.serialize(this._kmsProviders) - : this._kmsProviders; - - if (options.logger) { - mongoCryptOptions.logger = options.logger; - } - - if (options.extraOptions && options.extraOptions.cryptSharedLibPath) { - mongoCryptOptions.cryptSharedLibPath = options.extraOptions.cryptSharedLibPath; - } - - if (options.bypassQueryAnalysis) { - mongoCryptOptions.bypassQueryAnalysis = options.bypassQueryAnalysis; - } - - this._bypassMongocryptdAndCryptShared = this._bypassEncryption || options.bypassQueryAnalysis; - - if (options.extraOptions && options.extraOptions.cryptSharedLibSearchPaths) { - // Only for driver testing - mongoCryptOptions.cryptSharedLibSearchPaths = - options.extraOptions.cryptSharedLibSearchPaths; - } else if (!this._bypassMongocryptdAndCryptShared) { - mongoCryptOptions.cryptSharedLibSearchPaths = ['$SYSTEM']; - } - - Object.assign(mongoCryptOptions, { cryptoCallbacks }); - this._mongocrypt = new mc.MongoCrypt(mongoCryptOptions); - this._contextCounter = 0; - - if ( - options.extraOptions && - options.extraOptions.cryptSharedLibRequired && - !this.cryptSharedLibVersionInfo - ) { - throw new MongoError('`cryptSharedLibRequired` set but no crypt_shared library loaded'); - } - - // Only instantiate mongocryptd manager/client once we know for sure - // that we are not using the CSFLE shared library. - if (!this._bypassMongocryptdAndCryptShared && !this.cryptSharedLibVersionInfo) { - this._mongocryptdManager = new MongocryptdManager(options.extraOptions); - const clientOptions = { - useNewUrlParser: true, - useUnifiedTopology: true, - serverSelectionTimeoutMS: 10000 - }; - - if ( - options.extraOptions == null || - typeof options.extraOptions.mongocryptdURI !== 'string' - ) { - clientOptions.family = 4; - } - - this._mongocryptdClient = new MongoClient(this._mongocryptdManager.uri, clientOptions); - } - } - - /** - * @ignore - * @param {Function} callback Invoked when the mongocryptd client either successfully connects or errors - */ - init(callback) { - if (this._bypassMongocryptdAndCryptShared || this.cryptSharedLibVersionInfo) { - return callback(); - } - const _callback = (err, res) => { - if ( - err && - err.message && - (err.message.match(/timed out after/) || err.message.match(/ENOTFOUND/)) - ) { - callback( - new MongoError( - 'Unable to connect to `mongocryptd`, please make sure it is running or in your PATH for auto-spawn' - ) - ); - return; - } - - callback(err, res); - }; - - if (this._mongocryptdManager.bypassSpawn) { - return this._mongocryptdClient.connect().then( - result => { - return _callback(null, result); - }, - error => { - _callback(error, null); - } - ); - } - - this._mongocryptdManager.spawn(() => { - this._mongocryptdClient.connect().then( - result => { - return _callback(null, result); - }, - error => { - _callback(error, null); - } - ); - }); - } - - /** - * @ignore - * @param {Function} callback Invoked when the mongocryptd client either successfully disconnects or errors - */ - teardown(force, callback) { - if (this._mongocryptdClient) { - this._mongocryptdClient.close(force).then( - result => { - return callback(null, result); - }, - error => { - callback(error); - } - ); - } else { - callback(); - } - } - - /** - * @ignore - * Encrypt a command for a given namespace. - * - * @param {string} ns The namespace for this encryption context - * @param {object} cmd The command to encrypt - * @param {Function} callback - */ - encrypt(ns, cmd, options, callback) { - if (typeof ns !== 'string') { - throw new TypeError('Parameter `ns` must be a string'); - } - - if (typeof cmd !== 'object') { - throw new TypeError('Parameter `cmd` must be an object'); - } - - if (typeof options === 'function' && callback == null) { - callback = options; - options = {}; - } - - // If `bypassAutoEncryption` has been specified, don't encrypt - if (this._bypassEncryption) { - callback(undefined, cmd); - return; - } - - const bson = this._bson; - const commandBuffer = Buffer.isBuffer(cmd) ? cmd : bson.serialize(cmd, options); - - let context; - try { - context = this._mongocrypt.makeEncryptionContext(databaseNamespace(ns), commandBuffer); - } catch (err) { - callback(err, null); - return; - } - - // TODO: should these be accessors from the addon? - context.id = this._contextCounter++; - context.ns = ns; - context.document = cmd; - - const stateMachine = new StateMachine({ - bson, - ...options, - promoteValues: false, - promoteLongs: false, - proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions - }); - stateMachine.execute(this, context, callback); - } - - /** - * @ignore - * Decrypt a command response - * - * @param {Buffer} buffer - * @param {Function} callback - */ - decrypt(response, options, callback) { - if (typeof options === 'function' && callback == null) { - callback = options; - options = {}; - } - - const bson = this._bson; - const buffer = Buffer.isBuffer(response) ? response : bson.serialize(response, options); - - let context; - try { - context = this._mongocrypt.makeDecryptionContext(buffer); - } catch (err) { - callback(err, null); - return; - } - - // TODO: should this be an accessor from the addon? - context.id = this._contextCounter++; - - const stateMachine = new StateMachine({ - bson, - ...options, - proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions - }); - - const decorateResult = this[Symbol.for('@@mdb.decorateDecryptionResult')]; - stateMachine.execute(this, context, function (err, result) { - // Only for testing/internal usage - if (!err && result && decorateResult) { - err = decorateDecryptionResult(result, response, bson); - if (err) return callback(err); - } - callback(err, result); - }); - } - - /** - * Ask the user for KMS credentials. - * - * This returns anything that looks like the kmsProviders original input - * option. It can be empty, and any provider specified here will override - * the original ones. - */ - async askForKMSCredentials() { - return this._onKmsProviderRefresh - ? this._onKmsProviderRefresh() - : loadCredentials(this._kmsProviders); - } - - /** - * Return the current libmongocrypt's CSFLE shared library version - * as `{ version: bigint, versionStr: string }`, or `null` if no CSFLE - * shared library was loaded. - */ - get cryptSharedLibVersionInfo() { - return this._mongocrypt.cryptSharedLibVersionInfo; - } - - static get libmongocryptVersion() { - return mc.MongoCrypt.libmongocryptVersion; - } - } - - return { AutoEncrypter }; -}; - -/** - * Recurse through the (identically-shaped) `decrypted` and `original` - * objects and attach a `decryptedKeys` property on each sub-object that - * contained encrypted fields. Because we only call this on BSON responses, - * we do not need to worry about circular references. - * - * @internal - * @ignore - */ -function decorateDecryptionResult(decrypted, original, bson, isTopLevelDecorateCall = true) { - const decryptedKeys = Symbol.for('@@mdb.decryptedKeys'); - if (isTopLevelDecorateCall) { - // The original value could have been either a JS object or a BSON buffer - if (Buffer.isBuffer(original)) { - original = bson.deserialize(original); - } - if (Buffer.isBuffer(decrypted)) { - return new Error('Expected result of decryption to be deserialized BSON object'); - } - } - - if (!decrypted || typeof decrypted !== 'object') return; - for (const k of Object.keys(decrypted)) { - const originalValue = original[k]; - - // An object was decrypted by libmongocrypt if and only if it was - // a BSON Binary object with subtype 6. - if (originalValue && originalValue._bsontype === 'Binary' && originalValue.sub_type === 6) { - if (!decrypted[decryptedKeys]) { - Object.defineProperty(decrypted, decryptedKeys, { - value: [], - configurable: true, - enumerable: false, - writable: false - }); - } - decrypted[decryptedKeys].push(k); - // Do not recurse into this decrypted value. It could be a subdocument/array, - // in which case there is no original value associated with its subfields. - continue; - } - - decorateDecryptionResult(decrypted[k], originalValue, bson, false); - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/buffer_pool.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/buffer_pool.js deleted file mode 100644 index 23a21fe..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/buffer_pool.js +++ /dev/null @@ -1,123 +0,0 @@ -'use strict'; - -/** - * @internal - * @ignore - * */ -const kBuffers = Symbol('buffers'); -/** - * @internal - * @ignore - * - * */ -const kLength = Symbol('length'); - -/** - * A pool of Buffers which allow you to read them as if they were one - * @internal - * @ignore - */ -class BufferPool { - // [kBuffers]: Buffer[]; - // [kLength]: number; - - constructor() { - this[kBuffers] = []; - this[kLength] = 0; - } - - get length() { - return this[kLength]; - } - - /** - * Adds a buffer to the internal buffer pool list - * @param {Buffer} buffer - buffer to append to the pool - * @returns {void} - */ - append(buffer) { - this[kBuffers].push(buffer); - this[kLength] += buffer.length; - } - - /** - * Returns the requested number of bytes without consuming them - * @param {number} size - the number of bytes to return from the head of the pool - * @returns {Buffer} - */ - peek(size) { - return this.read(size, false); - } - - /** - * Reads the requested number of bytes, optionally consuming them - * @param {number} size - the number of bytes to return from the head of the pool - * @param {boolean} [consume] - whether the bytes returned should be removed, defaults to true - * @returns {Buffer} - */ - read(size, consume = true) { - if (typeof size !== 'number' || size < 0) { - throw new Error('Argument "size" must be a non-negative number'); - } - - if (size > this[kLength]) { - return Buffer.alloc(0); - } - - let result; - - // read the whole buffer - if (size === this.length) { - result = Buffer.concat(this[kBuffers]); - - if (consume) { - this[kBuffers] = []; - this[kLength] = 0; - } - } - - // size is within first buffer, no need to concat - else if (size <= this[kBuffers][0].length) { - result = this[kBuffers][0].slice(0, size); - if (consume) { - this[kBuffers][0] = this[kBuffers][0].slice(size); - this[kLength] -= size; - } - } - - // size is beyond first buffer, need to track and copy - else { - result = Buffer.allocUnsafe(size); - - let idx; - let offset = 0; - let bytesToCopy = size; - for (idx = 0; idx < this[kBuffers].length; ++idx) { - let bytesCopied; - if (bytesToCopy > this[kBuffers][idx].length) { - bytesCopied = this[kBuffers][idx].copy(result, offset, 0); - offset += bytesCopied; - } else { - bytesCopied = this[kBuffers][idx].copy(result, offset, 0, bytesToCopy); - if (consume) { - this[kBuffers][idx] = this[kBuffers][idx].slice(bytesCopied); - } - offset += bytesCopied; - break; - } - - bytesToCopy -= bytesCopied; - } - - // compact the internal buffer array - if (consume) { - this[kBuffers] = this[kBuffers].slice(idx); - this[kLength] -= size; - } - } - - return result; - } -} - -module.exports = { BufferPool }; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/clientEncryption.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/clientEncryption.js deleted file mode 100644 index fd46d5b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/clientEncryption.js +++ /dev/null @@ -1,821 +0,0 @@ -'use strict'; - -module.exports = function (modules) { - const mc = require('bindings')('mongocrypt'); - const common = require('./common'); - const databaseNamespace = common.databaseNamespace; - const collectionNamespace = common.collectionNamespace; - const promiseOrCallback = common.promiseOrCallback; - const maybeCallback = common.maybeCallback; - const StateMachine = modules.stateMachine.StateMachine; - const BSON = modules.mongodb.BSON; - const { - MongoCryptCreateEncryptedCollectionError, - MongoCryptCreateDataKeyError - } = require('./errors'); - const { loadCredentials } = require('./providers/index'); - const cryptoCallbacks = require('./cryptoCallbacks'); - const { promisify } = require('util'); - - /** @typedef {*} BSONValue - any serializable BSON value */ - /** @typedef {BSON.Long} Long A 64 bit integer, represented by the js-bson Long type.*/ - - /** - * @typedef {object} KMSProviders Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. - * @property {object} [aws] Configuration options for using 'aws' as your KMS provider - * @property {string} [aws.accessKeyId] The access key used for the AWS KMS provider - * @property {string} [aws.secretAccessKey] The secret access key used for the AWS KMS provider - * @property {object} [local] Configuration options for using 'local' as your KMS provider - * @property {Buffer} [local.key] The master key used to encrypt/decrypt data keys. A 96-byte long Buffer. - * @property {object} [azure] Configuration options for using 'azure' as your KMS provider - * @property {string} [azure.tenantId] The tenant ID identifies the organization for the account - * @property {string} [azure.clientId] The client ID to authenticate a registered application - * @property {string} [azure.clientSecret] The client secret to authenticate a registered application - * @property {string} [azure.identityPlatformEndpoint] If present, a host with optional port. E.g. "example.com" or "example.com:443". This is optional, and only needed if customer is using a non-commercial Azure instance (e.g. a government or China account, which use different URLs). Defaults to "login.microsoftonline.com" - * @property {object} [gcp] Configuration options for using 'gcp' as your KMS provider - * @property {string} [gcp.email] The service account email to authenticate - * @property {string|Binary} [gcp.privateKey] A PKCS#8 encrypted key. This can either be a base64 string or a binary representation - * @property {string} [gcp.endpoint] If present, a host with optional port. E.g. "example.com" or "example.com:443". Defaults to "oauth2.googleapis.com" - */ - - /** - * @typedef {object} DataKey A data key as stored in the database. - * @property {UUID} _id A unique identifier for the key. - * @property {number} version A numeric identifier for the schema version of this document. Implicitly 0 if unset. - * @property {string[]} [keyAltNames] Alternate names to search for keys by. Used for a per-document key scenario in support of GDPR scenarios. - * @property {Binary} keyMaterial Encrypted data key material, BinData type General. - * @property {Date} creationDate The datetime the wrapped data key material was imported into the Key Database. - * @property {Date} updateDate The datetime the wrapped data key material was last modified. On initial import, this value will be set to creationDate. - * @property {number} status 0 = enabled, 1 = disabled - * @property {object} masterKey the encrypted master key - */ - - /** - * @typedef {string} KmsProvider A string containing the name of a kms provider. Valid options are 'aws', 'azure', 'gcp', 'kmip', or 'local' - */ - - /** - * @typedef {object} ClientSession The ClientSession class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/ClientSession.html) - */ - - /** - * @typedef {object} DeleteResult The result of a delete operation from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/interfaces/DeleteResult.html) - * @property {boolean} acknowledged Indicates whether this write result was acknowledged. If not, then all other members of this result will be undefined. - * @property {number} deletedCount The number of documents that were deleted - */ - - /** - * @typedef {object} BulkWriteResult The BulkWriteResult class from the MongoDB Node driver (https://mongodb.github.io/node-mongodb-native/4.8/classes/BulkWriteResult.html) - */ - - /** - * @typedef {object} FindCursor The FindCursor class from the MongoDB Node driver (see https://mongodb.github.io/node-mongodb-native/4.8/classes/FindCursor.html) - */ - - /** - * The public interface for explicit in-use encryption - */ - class ClientEncryption { - /** - * Create a new encryption instance - * - * @param {MongoClient} client The client used for encryption - * @param {object} options Additional settings - * @param {string} options.keyVaultNamespace The namespace of the key vault, used to store encryption keys - * @param {object} options.tlsOptions An object that maps KMS provider names to TLS options. - * @param {MongoClient} [options.keyVaultClient] A `MongoClient` used to fetch keys from a key vault. Defaults to `client` - * @param {KMSProviders} [options.kmsProviders] options for specific KMS providers to use - * - * @example - * new ClientEncryption(mongoClient, { - * keyVaultNamespace: 'client.encryption', - * kmsProviders: { - * local: { - * key: masterKey // The master key used for encryption/decryption. A 96-byte long Buffer - * } - * } - * }); - * - * @example - * new ClientEncryption(mongoClient, { - * keyVaultNamespace: 'client.encryption', - * kmsProviders: { - * aws: { - * accessKeyId: AWS_ACCESS_KEY, - * secretAccessKey: AWS_SECRET_KEY - * } - * } - * }); - */ - constructor(client, options) { - this._client = client; - this._bson = options.bson || BSON || client.topology.bson; - this._proxyOptions = options.proxyOptions; - this._tlsOptions = options.tlsOptions; - this._kmsProviders = options.kmsProviders || {}; - - if (options.keyVaultNamespace == null) { - throw new TypeError('Missing required option `keyVaultNamespace`'); - } - - const mongoCryptOptions = { ...options, cryptoCallbacks }; - - mongoCryptOptions.kmsProviders = !Buffer.isBuffer(this._kmsProviders) - ? this._bson.serialize(this._kmsProviders) - : this._kmsProviders; - - this._onKmsProviderRefresh = options.onKmsProviderRefresh; - this._keyVaultNamespace = options.keyVaultNamespace; - this._keyVaultClient = options.keyVaultClient || client; - this._mongoCrypt = new mc.MongoCrypt(mongoCryptOptions); - } - - /** - * @typedef {Binary} ClientEncryptionDataKeyId - * The id of an existing dataKey. Is a bson Binary value. - * Can be used for {@link ClientEncryption.encrypt}, and can be used to directly - * query for the data key itself against the key vault namespace. - */ - - /** - * @callback ClientEncryptionCreateDataKeyCallback - * @param {Error} [error] If present, indicates an error that occurred in the creation of the data key - * @param {ClientEncryption~dataKeyId} [dataKeyId] If present, returns the id of the created data key - */ - - /** - * @typedef {object} AWSEncryptionKeyOptions Configuration options for making an AWS encryption key - * @property {string} region The AWS region of the KMS - * @property {string} key The Amazon Resource Name (ARN) to the AWS customer master key (CMK) - * @property {string} [endpoint] An alternate host to send KMS requests to. May include port number - */ - - /** - * @typedef {object} GCPEncryptionKeyOptions Configuration options for making a GCP encryption key - * @property {string} projectId GCP project id - * @property {string} location Location name (e.g. "global") - * @property {string} keyRing Key ring name - * @property {string} keyName Key name - * @property {string} [keyVersion] Key version - * @property {string} [endpoint] KMS URL, defaults to `https://www.googleapis.com/auth/cloudkms` - */ - - /** - * @typedef {object} AzureEncryptionKeyOptions Configuration options for making an Azure encryption key - * @property {string} keyName Key name - * @property {string} keyVaultEndpoint Key vault URL, typically `.vault.azure.net` - * @property {string} [keyVersion] Key version - */ - - /** - * Creates a data key used for explicit encryption and inserts it into the key vault namespace - * - * @param {string} provider The KMS provider used for this data key. Must be `'aws'`, `'azure'`, `'gcp'`, or `'local'` - * @param {object} [options] Options for creating the data key - * @param {AWSEncryptionKeyOptions|AzureEncryptionKeyOptions|GCPEncryptionKeyOptions} [options.masterKey] Idenfities a new KMS-specific key used to encrypt the new data key - * @param {string[]} [options.keyAltNames] An optional list of string alternate names used to reference a key. If a key is created with alternate names, then encryption may refer to the key by the unique alternate name instead of by _id. - * @param {ClientEncryptionCreateDataKeyCallback} [callback] Optional callback to invoke when key is created - * @returns {Promise|void} If no callback is provided, returns a Promise that either resolves with {@link ClientEncryption~dataKeyId the id of the created data key}, or rejects with an error. If a callback is provided, returns nothing. - * @example - * // Using callbacks to create a local key - * clientEncryption.createDataKey('local', (err, dataKey) => { - * if (err) { - * // This means creating the key failed. - * } else { - * // key creation succeeded - * } - * }); - * - * @example - * // Using async/await to create a local key - * const dataKeyId = await clientEncryption.createDataKey('local'); - * - * @example - * // Using async/await to create an aws key - * const dataKeyId = await clientEncryption.createDataKey('aws', { - * masterKey: { - * region: 'us-east-1', - * key: 'xxxxxxxxxxxxxx' // CMK ARN here - * } - * }); - * - * @example - * // Using async/await to create an aws key with a keyAltName - * const dataKeyId = await clientEncryption.createDataKey('aws', { - * masterKey: { - * region: 'us-east-1', - * key: 'xxxxxxxxxxxxxx' // CMK ARN here - * }, - * keyAltNames: [ 'mySpecialKey' ] - * }); - */ - createDataKey(provider, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - if (options == null) { - options = {}; - } - - const bson = this._bson; - - const dataKey = Object.assign({ provider }, options.masterKey); - - if (options.keyAltNames && !Array.isArray(options.keyAltNames)) { - throw new TypeError( - `Option "keyAltNames" must be an array of strings, but was of type ${typeof options.keyAltNames}.` - ); - } - - let keyAltNames = undefined; - if (options.keyAltNames && options.keyAltNames.length > 0) { - keyAltNames = options.keyAltNames.map((keyAltName, i) => { - if (typeof keyAltName !== 'string') { - throw new TypeError( - `Option "keyAltNames" must be an array of strings, but item at index ${i} was of type ${typeof keyAltName}` - ); - } - - return bson.serialize({ keyAltName }); - }); - } - - let keyMaterial = undefined; - if (options.keyMaterial) { - keyMaterial = bson.serialize({ keyMaterial: options.keyMaterial }); - } - - const dataKeyBson = bson.serialize(dataKey); - const context = this._mongoCrypt.makeDataKeyContext(dataKeyBson, { - keyAltNames, - keyMaterial - }); - const stateMachine = new StateMachine({ - bson, - proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions - }); - - return promiseOrCallback(callback, cb => { - stateMachine.execute(this, context, (err, dataKey) => { - if (err) { - cb(err, null); - return; - } - - const dbName = databaseNamespace(this._keyVaultNamespace); - const collectionName = collectionNamespace(this._keyVaultNamespace); - - this._keyVaultClient - .db(dbName) - .collection(collectionName) - .insertOne(dataKey, { writeConcern: { w: 'majority' } }) - .then( - result => { - return cb(null, result.insertedId); - }, - err => { - cb(err, null); - } - ); - }); - }); - } - - /** - * @typedef {object} RewrapManyDataKeyResult - * @property {BulkWriteResult} [bulkWriteResult] An optional BulkWriteResult, if any keys were matched and attempted to be re-wrapped. - */ - - /** - * Searches the keyvault for any data keys matching the provided filter. If there are matches, rewrapManyDataKey then attempts to re-wrap the data keys using the provided options. - * - * If no matches are found, then no bulk write is performed. - * - * @param {object} filter A valid MongoDB filter. Any documents matching this filter will be re-wrapped. - * @param {object} [options] - * @param {KmsProvider} options.provider The KMS provider to use when re-wrapping the data keys. - * @param {AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions} [options.masterKey] - * @returns {Promise} - * - * @example - * // rewrapping all data data keys (using a filter that matches all documents) - * const filter = {}; - * - * const result = await clientEncryption.rewrapManyDataKey(filter); - * if (result.bulkWriteResult != null) { - * // keys were re-wrapped, results will be available in the bulkWrite object. - * } - * - * @example - * // attempting to rewrap all data keys with no matches - * const filter = { _id: new Binary() } // assume _id matches no documents in the database - * const result = await clientEncryption.rewrapManyDataKey(filter); - * - * if (result.bulkWriteResult == null) { - * // no keys matched, `bulkWriteResult` does not exist on the result object - * } - */ - async rewrapManyDataKey(filter, options) { - const bson = this._bson; - - let keyEncryptionKeyBson = undefined; - if (options) { - const keyEncryptionKey = Object.assign({ provider: options.provider }, options.masterKey); - keyEncryptionKeyBson = bson.serialize(keyEncryptionKey); - } else { - // Always make sure `options` is an object below. - options = {}; - } - const filterBson = bson.serialize(filter); - const context = this._mongoCrypt.makeRewrapManyDataKeyContext( - filterBson, - keyEncryptionKeyBson - ); - const stateMachine = new StateMachine({ - bson, - proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions - }); - - const execute = promisify(stateMachine.execute.bind(stateMachine)); - - const dataKey = await execute(this, context); - if (!dataKey || dataKey.v.length === 0) { - return {}; - } - - const dbName = databaseNamespace(this._keyVaultNamespace); - const collectionName = collectionNamespace(this._keyVaultNamespace); - const replacements = dataKey.v.map(key => ({ - updateOne: { - filter: { _id: key._id }, - update: { - $set: { - masterKey: key.masterKey, - keyMaterial: key.keyMaterial - }, - $currentDate: { - updateDate: true - } - } - } - })); - - const result = await this._keyVaultClient - .db(dbName) - .collection(collectionName) - .bulkWrite(replacements, { - writeConcern: { w: 'majority' } - }); - - return { bulkWriteResult: result }; - } - - /** - * Deletes the key with the provided id from the keyvault, if it exists. - * - * @param {ClientEncryptionDataKeyId} _id - the id of the document to delete. - * @returns {Promise} Returns a promise that either resolves to a {@link DeleteResult} or rejects with an error. - * - * @example - * // delete a key by _id - * const id = new Binary(); // id is a bson binary subtype 4 object - * const { deletedCount } = await clientEncryption.deleteKey(id); - * - * if (deletedCount != null && deletedCount > 0) { - * // successful deletion - * } - * - */ - async deleteKey(_id) { - const dbName = databaseNamespace(this._keyVaultNamespace); - const collectionName = collectionNamespace(this._keyVaultNamespace); - return await this._keyVaultClient - .db(dbName) - .collection(collectionName) - .deleteOne({ _id }, { writeConcern: { w: 'majority' } }); - } - - /** - * Finds all the keys currently stored in the keyvault. - * - * This method will not throw. - * - * @returns {FindCursor} a FindCursor over all keys in the keyvault. - * @example - * // fetching all keys - * const keys = await clientEncryption.getKeys().toArray(); - */ - getKeys() { - const dbName = databaseNamespace(this._keyVaultNamespace); - const collectionName = collectionNamespace(this._keyVaultNamespace); - return this._keyVaultClient - .db(dbName) - .collection(collectionName) - .find({}, { readConcern: { level: 'majority' } }); - } - - /** - * Finds a key in the keyvault with the specified _id. - * - * @param {ClientEncryptionDataKeyId} _id - the id of the document to delete. - * @returns {Promise} Returns a promise that either resolves to a {@link DataKey} if a document matches the key or null if no documents - * match the id. The promise rejects with an error if an error is thrown. - * @example - * // getting a key by id - * const id = new Binary(); // id is a bson binary subtype 4 object - * const key = await clientEncryption.getKey(id); - * if (!key) { - * // key is null if there was no matching key - * } - */ - async getKey(_id) { - const dbName = databaseNamespace(this._keyVaultNamespace); - const collectionName = collectionNamespace(this._keyVaultNamespace); - return await this._keyVaultClient - .db(dbName) - .collection(collectionName) - .findOne({ _id }, { readConcern: { level: 'majority' } }); - } - - /** - * Finds a key in the keyvault which has the specified keyAltName. - * - * @param {string} keyAltName - a keyAltName to search for a key - * @returns {Promise} Returns a promise that either resolves to a {@link DataKey} if a document matches the key or null if no documents - * match the keyAltName. The promise rejects with an error if an error is thrown. - * @example - * // get a key by alt name - * const keyAltName = 'keyAltName'; - * const key = await clientEncryption.getKeyByAltName(keyAltName); - * if (!key) { - * // key is null if there is no matching key - * } - */ - async getKeyByAltName(keyAltName) { - const dbName = databaseNamespace(this._keyVaultNamespace); - const collectionName = collectionNamespace(this._keyVaultNamespace); - return await this._keyVaultClient - .db(dbName) - .collection(collectionName) - .findOne({ keyAltNames: keyAltName }, { readConcern: { level: 'majority' } }); - } - - /** - * Adds a keyAltName to a key identified by the provided _id. - * - * This method resolves to/returns the *old* key value (prior to adding the new altKeyName). - * - * @param {ClientEncryptionDataKeyId} _id The id of the document to update. - * @param {string} keyAltName - a keyAltName to search for a key - * @returns {Promise} Returns a promise that either resolves to a {@link DataKey} if a document matches the key or null if no documents - * match the id. The promise rejects with an error if an error is thrown. - * @example - * // adding an keyAltName to a data key - * const id = new Binary(); // id is a bson binary subtype 4 object - * const keyAltName = 'keyAltName'; - * const oldKey = await clientEncryption.addKeyAltName(id, keyAltName); - * if (!oldKey) { - * // null is returned if there is no matching document with an id matching the supplied id - * } - */ - async addKeyAltName(_id, keyAltName) { - const dbName = databaseNamespace(this._keyVaultNamespace); - const collectionName = collectionNamespace(this._keyVaultNamespace); - const { value } = await this._keyVaultClient - .db(dbName) - .collection(collectionName) - .findOneAndUpdate( - { _id }, - { $addToSet: { keyAltNames: keyAltName } }, - { writeConcern: { w: 'majority' }, returnDocument: 'before' } - ); - - return value; - } - - /** - * Adds a keyAltName to a key identified by the provided _id. - * - * This method resolves to/returns the *old* key value (prior to removing the new altKeyName). - * - * If the removed keyAltName is the last keyAltName for that key, the `altKeyNames` property is unset from the document. - * - * @param {ClientEncryptionDataKeyId} _id The id of the document to update. - * @param {string} keyAltName - a keyAltName to search for a key - * @returns {Promise} Returns a promise that either resolves to a {@link DataKey} if a document matches the key or null if no documents - * match the id. The promise rejects with an error if an error is thrown. - * @example - * // removing a key alt name from a data key - * const id = new Binary(); // id is a bson binary subtype 4 object - * const keyAltName = 'keyAltName'; - * const oldKey = await clientEncryption.removeKeyAltName(id, keyAltName); - * - * if (!oldKey) { - * // null is returned if there is no matching document with an id matching the supplied id - * } - */ - async removeKeyAltName(_id, keyAltName) { - const dbName = databaseNamespace(this._keyVaultNamespace); - const collectionName = collectionNamespace(this._keyVaultNamespace); - const pipeline = [ - { - $set: { - keyAltNames: { - $cond: [ - { - $eq: ['$keyAltNames', [keyAltName]] - }, - '$$REMOVE', - { - $filter: { - input: '$keyAltNames', - cond: { - $ne: ['$$this', keyAltName] - } - } - } - ] - } - } - } - ]; - const { value } = await this._keyVaultClient - .db(dbName) - .collection(collectionName) - .findOneAndUpdate({ _id }, pipeline, { - writeConcern: { w: 'majority' }, - returnDocument: 'before' - }); - - return value; - } - - /** - * @experimental Public Technical Preview - * - * A convenience method for creating an encrypted collection. - * This method will create data keys for any encryptedFields that do not have a `keyId` defined - * and then create a new collection with the full set of encryptedFields. - * - * @template {TSchema} - Schema for the collection being created - * @param {Db} db - A Node.js driver Db object with which to create the collection - * @param {string} name - The name of the collection to be created - * @param {object} options - Options for createDataKey and for createCollection - * @param {string} options.provider - KMS provider name - * @param {AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions} [options.masterKey] - masterKey to pass to createDataKey - * @param {CreateCollectionOptions} options.createCollectionOptions - options to pass to createCollection, must include `encryptedFields` - * @returns {Promise<{ collection: Collection, encryptedFields: Document }>} - created collection and generated encryptedFields - * @throws {MongoCryptCreateDataKeyError} - If part way through the process a createDataKey invocation fails, an error will be rejected that has the partial `encryptedFields` that were created. - * @throws {MongoCryptCreateEncryptedCollectionError} - If creating the collection fails, an error will be rejected that has the entire `encryptedFields` that were created. - */ - async createEncryptedCollection(db, name, options) { - const { - provider, - masterKey, - createCollectionOptions: { - encryptedFields: { ...encryptedFields }, - ...createCollectionOptions - } - } = options; - - if (Array.isArray(encryptedFields.fields)) { - const createDataKeyPromises = encryptedFields.fields.map(async field => - field == null || typeof field !== 'object' || field.keyId != null - ? field - : { - ...field, - keyId: await this.createDataKey(provider, { masterKey }) - } - ); - - const createDataKeyResolutions = await Promise.allSettled(createDataKeyPromises); - - encryptedFields.fields = createDataKeyResolutions.map((resolution, index) => - resolution.status === 'fulfilled' ? resolution.value : encryptedFields.fields[index] - ); - - const rejection = createDataKeyResolutions.find(({ status }) => status === 'rejected'); - if (rejection != null) { - throw new MongoCryptCreateDataKeyError({ encryptedFields, cause: rejection.reason }); - } - } - - try { - const collection = await db.createCollection(name, { - ...createCollectionOptions, - encryptedFields - }); - return { collection, encryptedFields }; - } catch (cause) { - throw new MongoCryptCreateEncryptedCollectionError({ encryptedFields, cause }); - } - } - - /** - * @callback ClientEncryptionEncryptCallback - * @param {Error} [err] If present, indicates an error that occurred in the process of encryption - * @param {Buffer} [result] If present, is the encrypted result - */ - - /** - * @typedef {object} RangeOptions - * min, max, sparsity, and range must match the values set in the encryptedFields of the destination collection. - * For double and decimal128, min/max/precision must all be set, or all be unset. - * @property {BSONValue} min is required if precision is set. - * @property {BSONValue} max is required if precision is set. - * @property {BSON.Long} sparsity - * @property {number | undefined} precision (may only be set for double or decimal128). - */ - - /** - * @typedef {object} EncryptOptions Options to provide when encrypting data. - * @property {ClientEncryptionDataKeyId} [keyId] The id of the Binary dataKey to use for encryption. - * @property {string} [keyAltName] A unique string name corresponding to an already existing dataKey. - * @property {string} [algorithm] The algorithm to use for encryption. Must be either `'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'`, `'AEAD_AES_256_CBC_HMAC_SHA_512-Random'`, `'Indexed'` or `'Unindexed'` - * @property {bigint | number} [contentionFactor] (experimental) - the contention factor. - * @property {'equality' | 'rangePreview'} queryType (experimental) - the query type supported. - * @property {RangeOptions} [rangeOptions] (experimental) The index options for a Queryable Encryption field supporting "rangePreview" queries. - */ - - /** - * Explicitly encrypt a provided value. Note that either `options.keyId` or `options.keyAltName` must - * be specified. Specifying both `options.keyId` and `options.keyAltName` is considered an error. - * - * @param {*} value The value that you wish to serialize. Must be of a type that can be serialized into BSON - * @param {EncryptOptions} options - * @param {ClientEncryptionEncryptCallback} [callback] Optional callback to invoke when value is encrypted - * @returns {Promise|void} If no callback is provided, returns a Promise that either resolves with the encrypted value, or rejects with an error. If a callback is provided, returns nothing. - * - * @example - * // Encryption with callback API - * function encryptMyData(value, callback) { - * clientEncryption.createDataKey('local', (err, keyId) => { - * if (err) { - * return callback(err); - * } - * clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }, callback); - * }); - * } - * - * @example - * // Encryption with async/await api - * async function encryptMyData(value) { - * const keyId = await clientEncryption.createDataKey('local'); - * return clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }); - * } - * - * @example - * // Encryption using a keyAltName - * async function encryptMyData(value) { - * await clientEncryption.createDataKey('local', { keyAltNames: 'mySpecialKey' }); - * return clientEncryption.encrypt(value, { keyAltName: 'mySpecialKey', algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }); - * } - */ - encrypt(value, options, callback) { - return maybeCallback(() => this._encrypt(value, false, options), callback); - } - - /** - * Encrypts a Match Expression or Aggregate Expression to query a range index. - * - * Only supported when queryType is "rangePreview" and algorithm is "RangePreview". - * - * @experimental The Range algorithm is experimental only. It is not intended for production use. It is subject to breaking changes. - * - * @param {object} expression a BSON document of one of the following forms: - * 1. A Match Expression of this form: - * `{$and: [{: {$gt: }}, {: {$lt: }}]}` - * 2. An Aggregate Expression of this form: - * `{$and: [{$gt: [, ]}, {$lt: [, ]}]}` - * - * `$gt` may also be `$gte`. `$lt` may also be `$lte`. - * - * @param {EncryptOptions} options - * @returns {Promise} Returns a Promise that either resolves with the encrypted value or rejects with an error. - */ - async encryptExpression(expression, options) { - return this._encrypt(expression, true, options); - } - - /** - * @callback ClientEncryption~decryptCallback - * @param {Error} [err] If present, indicates an error that occurred in the process of decryption - * @param {object} [result] If present, is the decrypted result - */ - - /** - * Explicitly decrypt a provided encrypted value - * - * @param {Buffer | Binary} value An encrypted value - * @param {ClientEncryption~decryptCallback} callback Optional callback to invoke when value is decrypted - * @returns {Promise|void} If no callback is provided, returns a Promise that either resolves with the decrypted value, or rejects with an error. If a callback is provided, returns nothing. - * - * @example - * // Decrypting value with callback API - * function decryptMyValue(value, callback) { - * clientEncryption.decrypt(value, callback); - * } - * - * @example - * // Decrypting value with async/await API - * async function decryptMyValue(value) { - * return clientEncryption.decrypt(value); - * } - */ - decrypt(value, callback) { - const bson = this._bson; - const valueBuffer = bson.serialize({ v: value }); - const context = this._mongoCrypt.makeExplicitDecryptionContext(valueBuffer); - - const stateMachine = new StateMachine({ - bson, - proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions - }); - - return promiseOrCallback(callback, cb => { - stateMachine.execute(this, context, (err, result) => { - if (err) { - cb(err, null); - return; - } - - cb(null, result.v); - }); - }); - } - - /** - * Ask the user for KMS credentials. - * - * This returns anything that looks like the kmsProviders original input - * option. It can be empty, and any provider specified here will override - * the original ones. - */ - async askForKMSCredentials() { - return this._onKmsProviderRefresh - ? this._onKmsProviderRefresh() - : loadCredentials(this._kmsProviders); - } - - static get libmongocryptVersion() { - return mc.MongoCrypt.libmongocryptVersion; - } - - /** - * A helper that perform explicit encryption of values and expressions. - * Explicitly encrypt a provided value. Note that either `options.keyId` or `options.keyAltName` must - * be specified. Specifying both `options.keyId` and `options.keyAltName` is considered an error. - * - * @param {*} value The value that you wish to encrypt. Must be of a type that can be serialized into BSON - * @param {boolean} expressionMode - a boolean that indicates whether or not to encrypt the value as an expression - * @param {EncryptOptions} options - * @returns the raw result of the call to stateMachine.execute(). When expressionMode is set to true, the return - * value will be a bson document. When false, the value will be a BSON Binary. - * - * @ignore - * - */ - async _encrypt(value, expressionMode, options) { - const bson = this._bson; - const valueBuffer = bson.serialize({ v: value }); - const contextOptions = Object.assign({}, options, { expressionMode }); - if (options.keyId) { - contextOptions.keyId = options.keyId.buffer; - } - if (options.keyAltName) { - const keyAltName = options.keyAltName; - if (options.keyId) { - throw new TypeError(`"options" cannot contain both "keyId" and "keyAltName"`); - } - const keyAltNameType = typeof keyAltName; - if (keyAltNameType !== 'string') { - throw new TypeError( - `"options.keyAltName" must be of type string, but was of type ${keyAltNameType}` - ); - } - - contextOptions.keyAltName = bson.serialize({ keyAltName }); - } - - if ('rangeOptions' in options) { - contextOptions.rangeOptions = bson.serialize(options.rangeOptions); - } - - const stateMachine = new StateMachine({ - bson, - proxyOptions: this._proxyOptions, - tlsOptions: this._tlsOptions - }); - const context = this._mongoCrypt.makeExplicitEncryptionContext(valueBuffer, contextOptions); - - const result = await stateMachine.executeAsync(this, context); - return result.v; - } - } - - return { ClientEncryption }; -}; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/common.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/common.js deleted file mode 100644 index 468b8c0..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/common.js +++ /dev/null @@ -1,98 +0,0 @@ -'use strict'; - -/** - * @ignore - * Helper function for logging. Enabled by setting the environment flag MONGODB_CRYPT_DEBUG. - * @param {*} msg Anything you want to be logged. - */ -function debug(msg) { - if (process.env.MONGODB_CRYPT_DEBUG) { - // eslint-disable-next-line no-console - console.error(msg); - } -} - -/** - * @ignore - * Gets the database portion of a namespace string - * @param {string} ns A string in the format of a namespace (database.collection) - * @returns {string} The database portion of the namespace - */ -function databaseNamespace(ns) { - return ns.split('.')[0]; -} -/** - * @ignore - * Gets the collection portion of a namespace string - * @param {string} ns A string in the format of a namespace (database.collection) - * @returns {string} The collection portion of the namespace - */ -function collectionNamespace(ns) { - return ns.split('.').slice(1).join('.'); -} - -function maybeCallback(promiseFn, callback) { - const promise = promiseFn(); - if (callback == null) { - return promise; - } - - promise.then( - result => process.nextTick(callback, undefined, result), - error => process.nextTick(callback, error) - ); - return; -} - -/** - * @ignore - * A helper function. Invokes a function that takes a callback as the final - * parameter. If a callback is supplied, then it is passed to the function. - * If not, a Promise is returned that resolves/rejects with the result of the - * callback - * @param {Function} [callback] an optional callback. - * @param {Function} fn A function that takes a callback - * @returns {Promise|void} Returns nothing if a callback is supplied, else returns a Promise. - */ -function promiseOrCallback(callback, fn) { - if (typeof callback === 'function') { - fn(function (err) { - if (err != null) { - try { - callback(err); - } catch (error) { - return process.nextTick(() => { - throw error; - }); - } - return; - } - - callback.apply(this, arguments); - }); - - return; - } - - return new Promise((resolve, reject) => { - fn(function (err, res) { - if (err != null) { - return reject(err); - } - - if (arguments.length > 2) { - return resolve(Array.prototype.slice.call(arguments, 1)); - } - - resolve(res); - }); - }); -} - -module.exports = { - debug, - databaseNamespace, - collectionNamespace, - promiseOrCallback, - maybeCallback -}; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/cryptoCallbacks.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/cryptoCallbacks.js deleted file mode 100644 index a036ff8..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/cryptoCallbacks.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict'; -const crypto = require('crypto'); - -function makeAES256Hook(method, mode) { - return function (key, iv, input, output) { - let result; - - try { - let cipher = crypto[method](mode, key, iv); - cipher.setAutoPadding(false); - result = cipher.update(input); - const final = cipher.final(); - if (final.length > 0) { - result = Buffer.concat([result, final]); - } - } catch (e) { - return e; - } - - result.copy(output); - return result.length; - }; -} - -function randomHook(buffer, count) { - try { - crypto.randomFillSync(buffer, 0, count); - } catch (e) { - return e; - } - return count; -} - -function sha256Hook(input, output) { - let result; - try { - result = crypto.createHash('sha256').update(input).digest(); - } catch (e) { - return e; - } - - result.copy(output); - return result.length; -} - -function makeHmacHook(algorithm) { - return (key, input, output) => { - let result; - try { - result = crypto.createHmac(algorithm, key).update(input).digest(); - } catch (e) { - return e; - } - - result.copy(output); - return result.length; - }; -} - -function signRsaSha256Hook(key, input, output) { - let result; - try { - const signer = crypto.createSign('sha256WithRSAEncryption'); - const privateKey = Buffer.from( - `-----BEGIN PRIVATE KEY-----\n${key.toString('base64')}\n-----END PRIVATE KEY-----\n` - ); - - result = signer.update(input).end().sign(privateKey); - } catch (e) { - return e; - } - - result.copy(output); - return result.length; -} - -module.exports = { - aes256CbcEncryptHook: makeAES256Hook('createCipheriv', 'aes-256-cbc'), - aes256CbcDecryptHook: makeAES256Hook('createDecipheriv', 'aes-256-cbc'), - aes256CtrEncryptHook: makeAES256Hook('createCipheriv', 'aes-256-ctr'), - aes256CtrDecryptHook: makeAES256Hook('createDecipheriv', 'aes-256-ctr'), - randomHook, - hmacSha512Hook: makeHmacHook('sha512'), - hmacSha256Hook: makeHmacHook('sha256'), - sha256Hook, - signRsaSha256Hook -}; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/errors.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/errors.js deleted file mode 100644 index b2f0a3c..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/errors.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -/** - * @class - * An error indicating that something went wrong specifically with MongoDB Client Encryption - */ -class MongoCryptError extends Error { - constructor(message, options = {}) { - super(message); - if (options.cause != null) { - this.cause = options.cause; - } - } - - get name() { - return 'MongoCryptError'; - } -} - -/** - * @experimental Public Technical Preview - * @class - * An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create data keys - */ -class MongoCryptCreateDataKeyError extends MongoCryptError { - constructor({ encryptedFields, cause }) { - super(`Unable to complete creating data keys: ${cause.message}`, { cause }); - this.encryptedFields = encryptedFields; - } - - get name() { - return 'MongoCryptCreateDataKeyError'; - } -} - -/** - * @experimental Public Technical Preview - * @class - * An error indicating that `ClientEncryption.createEncryptedCollection()` failed to create a collection - */ -class MongoCryptCreateEncryptedCollectionError extends MongoCryptError { - constructor({ encryptedFields, cause }) { - super(`Unable to create collection: ${cause.message}`, { cause }); - this.encryptedFields = encryptedFields; - } - - get name() { - return 'MongoCryptCreateEncryptedCollectionError'; - } -} - -/** - * @class - * An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials. - */ -class MongoCryptAzureKMSRequestError extends MongoCryptError { - /** - * @param {string} message - * @param {object | undefined} body - */ - constructor(message, body) { - super(message); - this.body = body; - } -} - -class MongoCryptKMSRequestNetworkTimeoutError extends MongoCryptError {} - -module.exports = { - MongoCryptError, - MongoCryptKMSRequestNetworkTimeoutError, - MongoCryptAzureKMSRequestError, - MongoCryptCreateDataKeyError, - MongoCryptCreateEncryptedCollectionError -}; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/index.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/index.js deleted file mode 100644 index b2f760b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/index.js +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; - -let defaultModule; -function loadDefaultModule() { - if (!defaultModule) { - defaultModule = extension(require('mongodb')); - } - - return defaultModule; -} - -const { - MongoCryptError, - MongoCryptCreateEncryptedCollectionError, - MongoCryptCreateDataKeyError, - MongoCryptAzureKMSRequestError, - MongoCryptKMSRequestNetworkTimeoutError -} = require('./errors'); - -const { fetchAzureKMSToken } = require('./providers/index'); - -function extension(mongodb) { - const modules = { mongodb }; - - modules.stateMachine = require('./stateMachine')(modules); - modules.autoEncrypter = require('./autoEncrypter')(modules); - modules.clientEncryption = require('./clientEncryption')(modules); - - const exports = { - AutoEncrypter: modules.autoEncrypter.AutoEncrypter, - ClientEncryption: modules.clientEncryption.ClientEncryption, - MongoCryptError, - MongoCryptCreateEncryptedCollectionError, - MongoCryptCreateDataKeyError, - MongoCryptAzureKMSRequestError, - MongoCryptKMSRequestNetworkTimeoutError - }; - - Object.defineProperty(exports, '___azureKMSProseTestExports', { - enumerable: false, - configurable: false, - value: fetchAzureKMSToken - }); - - return exports; -} - -module.exports = { - extension, - MongoCryptError, - MongoCryptCreateEncryptedCollectionError, - MongoCryptCreateDataKeyError, - MongoCryptAzureKMSRequestError, - MongoCryptKMSRequestNetworkTimeoutError, - get AutoEncrypter() { - const m = loadDefaultModule(); - delete module.exports.AutoEncrypter; - module.exports.AutoEncrypter = m.AutoEncrypter; - return m.AutoEncrypter; - }, - get ClientEncryption() { - const m = loadDefaultModule(); - delete module.exports.ClientEncryption; - module.exports.ClientEncryption = m.ClientEncryption; - return m.ClientEncryption; - } -}; - -Object.defineProperty(module.exports, '___azureKMSProseTestExports', { - enumerable: false, - configurable: false, - value: fetchAzureKMSToken -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/mongocryptdManager.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/mongocryptdManager.js deleted file mode 100644 index 076c584..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/mongocryptdManager.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -const spawn = require('child_process').spawn; - -/** - * @ignore - * An internal class that handles spawning a mongocryptd. - */ -class MongocryptdManager { - /** - * @ignore - * Creates a new Mongocryptd Manager - * @param {AutoEncrypter~AutoEncryptionExtraOptions} [extraOptions] extra options that determine how/when to spawn a mongocryptd - */ - constructor(extraOptions) { - extraOptions = extraOptions || {}; - - this.uri = - typeof extraOptions.mongocryptdURI === 'string' && extraOptions.mongocryptdURI.length > 0 - ? extraOptions.mongocryptdURI - : MongocryptdManager.DEFAULT_MONGOCRYPTD_URI; - - this.bypassSpawn = !!extraOptions.mongocryptdBypassSpawn; - - this.spawnPath = extraOptions.mongocryptdSpawnPath || ''; - this.spawnArgs = []; - if (Array.isArray(extraOptions.mongocryptdSpawnArgs)) { - this.spawnArgs = this.spawnArgs.concat(extraOptions.mongocryptdSpawnArgs); - } - if ( - this.spawnArgs - .filter(arg => typeof arg === 'string') - .every(arg => arg.indexOf('--idleShutdownTimeoutSecs') < 0) - ) { - this.spawnArgs.push('--idleShutdownTimeoutSecs', 60); - } - } - - /** - * @ignore - * Will check to see if a mongocryptd is up. If it is not up, it will attempt - * to spawn a mongocryptd in a detached process, and then wait for it to be up. - * @param {Function} callback Invoked when we think a mongocryptd is up - */ - spawn(callback) { - const cmdName = this.spawnPath || 'mongocryptd'; - - // Spawned with stdio: ignore and detatched:true - // to ensure child can outlive parent. - this._child = spawn(cmdName, this.spawnArgs, { - stdio: 'ignore', - detached: true - }); - - this._child.on('error', () => {}); - - // unref child to remove handle from event loop - this._child.unref(); - - process.nextTick(callback); - } -} - -MongocryptdManager.DEFAULT_MONGOCRYPTD_URI = 'mongodb://localhost:27020'; - -module.exports = { MongocryptdManager }; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/aws.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/aws.js deleted file mode 100644 index b71c2b1..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/aws.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -let awsCredentialProviders = null; -/** @ignore */ -async function loadAWSCredentials(kmsProviders) { - if (awsCredentialProviders == null) { - try { - // Ensure you always wrap an optional require in the try block NODE-3199 - awsCredentialProviders = require('@aws-sdk/credential-providers'); - // eslint-disable-next-line no-empty - } catch {} - } - - if (awsCredentialProviders != null) { - const { fromNodeProviderChain } = awsCredentialProviders; - const provider = fromNodeProviderChain(); - // The state machine is the only place calling this so it will - // catch if there is a rejection here. - const aws = await provider(); - return { ...kmsProviders, aws }; - } - - return kmsProviders; -} - -module.exports = { loadAWSCredentials }; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/azure.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/azure.js deleted file mode 100644 index bd52256..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/azure.js +++ /dev/null @@ -1,178 +0,0 @@ -'use strict'; - -const { - MongoCryptAzureKMSRequestError, - MongoCryptKMSRequestNetworkTimeoutError -} = require('../errors'); -const utils = require('./utils'); - -const MINIMUM_TOKEN_REFRESH_IN_MILLISECONDS = 6000; - -/** - * @class - * @ignore - */ -class AzureCredentialCache { - constructor() { - /** - * @type { { accessToken: string, expiresOnTimestamp: number } | null} - */ - this.cachedToken = null; - } - - async getToken() { - if (this.needsRefresh(this.cachedToken)) { - this.cachedToken = await this._getToken(); - } - - return { accessToken: this.cachedToken.accessToken }; - } - - needsRefresh(token) { - if (token == null) { - return true; - } - const timeUntilExpirationMS = token.expiresOnTimestamp - Date.now(); - return timeUntilExpirationMS <= MINIMUM_TOKEN_REFRESH_IN_MILLISECONDS; - } - - /** - * exposed for testing - * @ignore - */ - resetCache() { - this.cachedToken = null; - } - - /** - * exposed for testing - * @ignore - */ - _getToken() { - return fetchAzureKMSToken(); - } -} -/** - * @type{ AzureCredentialCache } - * @ignore - */ -let tokenCache = new AzureCredentialCache(); - -/** - * @typedef {object} KmsRequestResponsePayload - * @property {string | undefined} access_token - * @property {string | undefined} expires_in - * - * @ignore - */ - -/** - * @param { {body: string, status: number }} response - * @returns { Promise<{ accessToken: string, expiresOnTimestamp: number } >} - * @ignore - */ -async function parseResponse(response) { - const { status, body: rawBody } = response; - - /** - * @type { KmsRequestResponsePayload } - */ - const body = (() => { - try { - return JSON.parse(rawBody); - } catch { - throw new MongoCryptAzureKMSRequestError('Malformed JSON body in GET request.'); - } - })(); - - if (status !== 200) { - throw new MongoCryptAzureKMSRequestError('Unable to complete request.', body); - } - - if (!body.access_token) { - throw new MongoCryptAzureKMSRequestError( - 'Malformed response body - missing field `access_token`.' - ); - } - - if (!body.expires_in) { - throw new MongoCryptAzureKMSRequestError( - 'Malformed response body - missing field `expires_in`.' - ); - } - - const expiresInMS = Number(body.expires_in) * 1000; - if (Number.isNaN(expiresInMS)) { - throw new MongoCryptAzureKMSRequestError( - 'Malformed response body - unable to parse int from `expires_in` field.' - ); - } - - return { - accessToken: body.access_token, - expiresOnTimestamp: Date.now() + expiresInMS - }; -} - -/** - * @param {object} options - * @param {object | undefined} [options.headers] - * @param {URL | undefined} [options.url] - * - * @ignore - */ -function prepareRequest(options) { - const url = - options.url == null - ? new URL('http://169.254.169.254/metadata/identity/oauth2/token') - : new URL(options.url); - - url.searchParams.append('api-version', '2018-02-01'); - url.searchParams.append('resource', 'https://vault.azure.net'); - - const headers = { ...options.headers, 'Content-Type': 'application/json', Metadata: true }; - return { headers, url }; -} - -/** - * @typedef {object} AzureKMSRequestOptions - * @property {object | undefined} headers - * @property {URL | undefined} url - * @ignore - */ - -/** - * @typedef {object} AzureKMSRequestResponse - * @property {string} accessToken - * @property {number} expiresOnTimestamp - * @ignore - */ - -/** - * exported only for testing purposes in the driver - * - * @param {AzureKMSRequestOptions} options - * @returns {Promise} - * - * @ignore - */ -async function fetchAzureKMSToken(options = {}) { - const { headers, url } = prepareRequest(options); - const response = await utils.get(url, { headers }).catch(error => { - if (error instanceof MongoCryptKMSRequestNetworkTimeoutError) { - throw new MongoCryptAzureKMSRequestError(`[Azure KMS] ${error.message}`); - } - throw error; - }); - return parseResponse(response); -} - -/** - * @ignore - */ -async function loadAzureCredentials(kmsProviders) { - const azure = await tokenCache.getToken(); - return { ...kmsProviders, azure }; -} - -module.exports = { loadAzureCredentials, AzureCredentialCache, fetchAzureKMSToken, tokenCache }; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/gcp.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/gcp.js deleted file mode 100644 index 01edcfd..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/gcp.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -let gcpMetadata = null; -/** @ignore */ -async function loadGCPCredentials(kmsProviders) { - if (gcpMetadata == null) { - try { - // Ensure you always wrap an optional require in the try block NODE-3199 - gcpMetadata = require('gcp-metadata'); - // eslint-disable-next-line no-empty - } catch {} - } - - if (gcpMetadata != null) { - const { access_token: accessToken } = await gcpMetadata.instance({ - property: 'service-accounts/default/token' - }); - return { ...kmsProviders, gcp: { accessToken } }; - } - - return kmsProviders; -} - -module.exports = { loadGCPCredentials }; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/index.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/index.js deleted file mode 100644 index 33847a5..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/index.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; - -const { loadAWSCredentials } = require('./aws'); -const { loadAzureCredentials, fetchAzureKMSToken } = require('./azure'); -const { loadGCPCredentials } = require('./gcp'); - -/** - * Auto credential fetching should only occur when the provider is defined on the kmsProviders map - * and the settings are an empty object. - * - * This is distinct from a nullish provider key. - * - * @param {'aws' | 'gcp' | 'azure'} provider - * @param {object} kmsProviders - * - * @ignore - */ -function isEmptyCredentials(provider, kmsProviders) { - return ( - provider in kmsProviders && - kmsProviders[provider] != null && - typeof kmsProviders[provider] === 'object' && - Object.keys(kmsProviders[provider]).length === 0 - ); -} - -/** - * Load cloud provider credentials for the user provided KMS providers. - * Credentials will only attempt to get loaded if they do not exist - * and no existing credentials will get overwritten. - * - * @param {object} kmsProviders - The user provided KMS providers. - * @returns {object} The new kms providers. - * - * @ignore - */ -async function loadCredentials(kmsProviders) { - let finalKMSProviders = kmsProviders; - - if (isEmptyCredentials('aws', kmsProviders)) { - finalKMSProviders = await loadAWSCredentials(finalKMSProviders); - } - - if (isEmptyCredentials('gcp', kmsProviders)) { - finalKMSProviders = await loadGCPCredentials(finalKMSProviders); - } - - if (isEmptyCredentials('azure', kmsProviders)) { - finalKMSProviders = await loadAzureCredentials(finalKMSProviders); - } - return finalKMSProviders; -} - -module.exports = { loadCredentials, isEmptyCredentials, fetchAzureKMSToken }; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/utils.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/utils.js deleted file mode 100644 index 844c136..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/utils.js +++ /dev/null @@ -1,39 +0,0 @@ -'use strict'; - -const { MongoCryptKMSRequestNetworkTimeoutError } = require('../errors'); -const http = require('http'); - -/** - * @param {URL | string} url - * @param {http.RequestOptions} options - * - * @returns { Promise<{ body: string, status: number }> } - * @ignore - */ -function get(url, options = {}) { - return new Promise((resolve, reject) => { - let timeoutId; - const request = http - .get(url, options, response => { - response.setEncoding('utf8'); - let body = ''; - response.on('data', chunk => (body += chunk)); - response.on('end', () => { - clearTimeout(timeoutId); - resolve({ status: response.statusCode, body }); - }); - }) - .on('error', error => { - clearTimeout(timeoutId); - reject(error); - }) - .end(); - timeoutId = setTimeout(() => { - request.destroy( - new MongoCryptKMSRequestNetworkTimeoutError(`request timed out after 10 seconds`) - ); - }, 10000); - }); -} - -module.exports = { get }; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/stateMachine.js b/ext/libmongocrypt/libmongocrypt/bindings/node/lib/stateMachine.js deleted file mode 100644 index 30215c3..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/lib/stateMachine.js +++ /dev/null @@ -1,492 +0,0 @@ -'use strict'; - -const { promisify } = require('util'); - -module.exports = function (modules) { - const tls = require('tls'); - const net = require('net'); - const fs = require('fs'); - const { once } = require('events'); - const { SocksClient } = require('socks'); - - // Try first to import 4.x name, fallback to 3.x name - const MongoNetworkTimeoutError = - modules.mongodb.MongoNetworkTimeoutError || modules.mongodb.MongoTimeoutError; - - const common = require('./common'); - const debug = common.debug; - const databaseNamespace = common.databaseNamespace; - const collectionNamespace = common.collectionNamespace; - const { MongoCryptError } = require('./errors'); - const { BufferPool } = require('./buffer_pool'); - - // libmongocrypt states - const MONGOCRYPT_CTX_ERROR = 0; - const MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1; - const MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2; - const MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3; - const MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS = 7; - const MONGOCRYPT_CTX_NEED_KMS = 4; - const MONGOCRYPT_CTX_READY = 5; - const MONGOCRYPT_CTX_DONE = 6; - - const HTTPS_PORT = 443; - - const stateToString = new Map([ - [MONGOCRYPT_CTX_ERROR, 'MONGOCRYPT_CTX_ERROR'], - [MONGOCRYPT_CTX_NEED_MONGO_COLLINFO, 'MONGOCRYPT_CTX_NEED_MONGO_COLLINFO'], - [MONGOCRYPT_CTX_NEED_MONGO_MARKINGS, 'MONGOCRYPT_CTX_NEED_MONGO_MARKINGS'], - [MONGOCRYPT_CTX_NEED_MONGO_KEYS, 'MONGOCRYPT_CTX_NEED_MONGO_KEYS'], - [MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS, 'MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS'], - [MONGOCRYPT_CTX_NEED_KMS, 'MONGOCRYPT_CTX_NEED_KMS'], - [MONGOCRYPT_CTX_READY, 'MONGOCRYPT_CTX_READY'], - [MONGOCRYPT_CTX_DONE, 'MONGOCRYPT_CTX_DONE'] - ]); - - const INSECURE_TLS_OPTIONS = [ - 'tlsInsecure', - 'tlsAllowInvalidCertificates', - 'tlsAllowInvalidHostnames', - 'tlsDisableOCSPEndpointCheck', - 'tlsDisableCertificateRevocationCheck' - ]; - - /** - * @ignore - * @callback StateMachine~executeCallback - * @param {Error} [err] If present, indicates that the execute call failed with the given error - * @param {object} [result] If present, is the result of executing the state machine. - * @returns {void} - */ - - /** - * @ignore - * @callback StateMachine~fetchCollectionInfoCallback - * @param {Error} [err] If present, indicates that fetching the collection info failed with the given error - * @param {object} [result] If present, is the fetched collection info for the first collection to match the given filter - * @returns {void} - */ - - /** - * @ignore - * @callback StateMachine~markCommandCallback - * @param {Error} [err] If present, indicates that marking the command failed with the given error - * @param {Buffer} [result] If present, is the marked command serialized into bson - * @returns {void} - */ - - /** - * @ignore - * @callback StateMachine~fetchKeysCallback - * @param {Error} [err] If present, indicates that fetching the keys failed with the given error - * @param {object[]} [result] If present, is all the keys from the keyVault collection that matched the given filter - */ - - /** - * @ignore - * An internal class that executes across a MongoCryptContext until either - * a finishing state or an error is reached. Do not instantiate directly. - * @class StateMachine - */ - class StateMachine { - constructor(options) { - this.options = options || {}; - this.bson = options.bson; - - this.executeAsync = promisify((autoEncrypter, context, callback) => - this.execute(autoEncrypter, context, callback) - ); - } - - /** - * @ignore - * Executes the state machine according to the specification - * @param {AutoEncrypter|ClientEncryption} autoEncrypter The JS encryption object - * @param {object} context The C++ context object returned from the bindings - * @param {StateMachine~executeCallback} callback Invoked with the result/error of executing the state machine - * @returns {void} - */ - execute(autoEncrypter, context, callback) { - const bson = this.bson; - const keyVaultNamespace = autoEncrypter._keyVaultNamespace; - const keyVaultClient = autoEncrypter._keyVaultClient; - const metaDataClient = autoEncrypter._metaDataClient; - const mongocryptdClient = autoEncrypter._mongocryptdClient; - const mongocryptdManager = autoEncrypter._mongocryptdManager; - - debug(`[context#${context.id}] ${stateToString.get(context.state) || context.state}`); - switch (context.state) { - case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: { - const filter = bson.deserialize(context.nextMongoOperation()); - this.fetchCollectionInfo(metaDataClient, context.ns, filter, (err, collInfo) => { - if (err) { - return callback(err, null); - } - - if (collInfo) { - context.addMongoOperationResponse(collInfo); - } - - context.finishMongoOperation(); - this.execute(autoEncrypter, context, callback); - }); - - return; - } - - case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: { - const command = context.nextMongoOperation(); - this.markCommand(mongocryptdClient, context.ns, command, (err, markedCommand) => { - if (err) { - // If we are not bypassing spawning, then we should retry once on a MongoTimeoutError (server selection error) - if ( - err instanceof MongoNetworkTimeoutError && - mongocryptdManager && - !mongocryptdManager.bypassSpawn - ) { - mongocryptdManager.spawn(() => { - // TODO: should we be shadowing the variables here? - this.markCommand(mongocryptdClient, context.ns, command, (err, markedCommand) => { - if (err) return callback(err, null); - - context.addMongoOperationResponse(markedCommand); - context.finishMongoOperation(); - - this.execute(autoEncrypter, context, callback); - }); - }); - return; - } - return callback(err, null); - } - context.addMongoOperationResponse(markedCommand); - context.finishMongoOperation(); - - this.execute(autoEncrypter, context, callback); - }); - - return; - } - - case MONGOCRYPT_CTX_NEED_MONGO_KEYS: { - const filter = context.nextMongoOperation(); - this.fetchKeys(keyVaultClient, keyVaultNamespace, filter, (err, keys) => { - if (err) return callback(err, null); - keys.forEach(key => { - context.addMongoOperationResponse(bson.serialize(key)); - }); - - context.finishMongoOperation(); - this.execute(autoEncrypter, context, callback); - }); - - return; - } - - case MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: { - autoEncrypter - .askForKMSCredentials() - .then(kmsProviders => { - context.provideKMSProviders( - !Buffer.isBuffer(kmsProviders) ? bson.serialize(kmsProviders) : kmsProviders - ); - this.execute(autoEncrypter, context, callback); - }) - .catch(err => { - callback(err, null); - }); - - return; - } - - case MONGOCRYPT_CTX_NEED_KMS: { - const promises = []; - - let request; - while ((request = context.nextKMSRequest())) { - promises.push(this.kmsRequest(request)); - } - - Promise.all(promises) - .then(() => { - context.finishKMSRequests(); - this.execute(autoEncrypter, context, callback); - }) - .catch(err => { - callback(err, null); - }); - - return; - } - - // terminal states - case MONGOCRYPT_CTX_READY: { - const finalizedContext = context.finalize(); - // TODO: Maybe rework the logic here so that instead of doing - // the callback here, finalize stores the result, and then - // we wait to MONGOCRYPT_CTX_DONE to do the callback - if (context.state === MONGOCRYPT_CTX_ERROR) { - const message = context.status.message || 'Finalization error'; - callback(new MongoCryptError(message)); - return; - } - callback(null, bson.deserialize(finalizedContext, this.options)); - return; - } - case MONGOCRYPT_CTX_ERROR: { - const message = context.status.message; - callback(new MongoCryptError(message)); - return; - } - - case MONGOCRYPT_CTX_DONE: - callback(); - return; - - default: - callback(new MongoCryptError(`Unknown state: ${context.state}`)); - return; - } - } - - /** - * @ignore - * Handles the request to the KMS service. Exposed for testing purposes. Do not directly invoke. - * @param {*} kmsContext A C++ KMS context returned from the bindings - * @returns {Promise} A promise that resolves when the KMS reply has be fully parsed - */ - kmsRequest(request) { - const parsedUrl = request.endpoint.split(':'); - const port = parsedUrl[1] != null ? Number.parseInt(parsedUrl[1], 10) : HTTPS_PORT; - const options = { host: parsedUrl[0], servername: parsedUrl[0], port }; - const message = request.message; - - // TODO(NODE-3959): We can adopt `for-await on(socket, 'data')` with logic to control abort - // eslint-disable-next-line no-async-promise-executor - return new Promise(async (resolve, reject) => { - const buffer = new BufferPool(); - - let socket; - let rawSocket; - - function destroySockets() { - for (const sock of [socket, rawSocket]) { - if (sock) { - sock.removeAllListeners(); - sock.destroy(); - } - } - } - - function ontimeout() { - destroySockets(); - reject(new MongoCryptError('KMS request timed out')); - } - - function onerror(err) { - destroySockets(); - const mcError = new MongoCryptError('KMS request failed'); - mcError.originalError = err; - reject(mcError); - } - - if (this.options.proxyOptions && this.options.proxyOptions.proxyHost) { - rawSocket = net.connect({ - host: this.options.proxyOptions.proxyHost, - port: this.options.proxyOptions.proxyPort || 1080 - }); - - rawSocket.on('timeout', ontimeout); - rawSocket.on('error', onerror); - try { - await once(rawSocket, 'connect'); - options.socket = ( - await SocksClient.createConnection({ - existing_socket: rawSocket, - command: 'connect', - destination: { host: options.host, port: options.port }, - proxy: { - // host and port are ignored because we pass existing_socket - host: 'iLoveJavaScript', - port: 0, - type: 5, - userId: this.options.proxyOptions.proxyUsername, - password: this.options.proxyOptions.proxyPassword - } - }) - ).socket; - } catch (err) { - return onerror(err); - } - } - - const tlsOptions = this.options.tlsOptions; - if (tlsOptions) { - const kmsProvider = request.kmsProvider; - const providerTlsOptions = tlsOptions[kmsProvider]; - if (providerTlsOptions) { - const error = this.validateTlsOptions(kmsProvider, providerTlsOptions); - if (error) reject(error); - this.setTlsOptions(providerTlsOptions, options); - } - } - socket = tls.connect(options, () => { - socket.write(message); - }); - - socket.once('timeout', ontimeout); - socket.once('error', onerror); - - socket.on('data', data => { - buffer.append(data); - while (request.bytesNeeded > 0 && buffer.length) { - const bytesNeeded = Math.min(request.bytesNeeded, buffer.length); - request.addResponse(buffer.read(bytesNeeded)); - } - - if (request.bytesNeeded <= 0) { - // There's no need for any more activity on this socket at this point. - destroySockets(); - resolve(); - } - }); - }); - } - - /** - * @ignore - * Validates the provided TLS options are secure. - * - * @param {string} kmsProvider The KMS provider name. - * @param {ClientEncryptionTLSOptions} tlsOptions The client TLS options for the provider. - * - * @returns {Error} If any option is invalid. - */ - validateTlsOptions(kmsProvider, tlsOptions) { - const tlsOptionNames = Object.keys(tlsOptions); - for (const option of INSECURE_TLS_OPTIONS) { - if (tlsOptionNames.includes(option)) { - return new MongoCryptError( - `Insecure TLS options prohibited for ${kmsProvider}: ${option}` - ); - } - } - } - - /** - * @ignore - * Sets only the valid secure TLS options. - * - * @param {ClientEncryptionTLSOptions} tlsOptions The client TLS options for the provider. - * @param {Object} options The existing connection options. - */ - setTlsOptions(tlsOptions, options) { - if (tlsOptions.tlsCertificateKeyFile) { - const cert = fs.readFileSync(tlsOptions.tlsCertificateKeyFile); - options.cert = options.key = cert; - } - if (tlsOptions.tlsCAFile) { - options.ca = fs.readFileSync(tlsOptions.tlsCAFile); - } - if (tlsOptions.tlsCertificateKeyFilePassword) { - options.passphrase = tlsOptions.tlsCertificateKeyFilePassword; - } - } - - /** - * @ignore - * Fetches collection info for a provided namespace, when libmongocrypt - * enters the `MONGOCRYPT_CTX_NEED_MONGO_COLLINFO` state. The result is - * used to inform libmongocrypt of the schema associated with this - * namespace. Exposed for testing purposes. Do not directly invoke. - * - * @param {MongoClient} client A MongoClient connected to the topology - * @param {string} ns The namespace to list collections from - * @param {object} filter A filter for the listCollections command - * @param {StateMachine~fetchCollectionInfoCallback} callback Invoked with the info of the requested collection, or with an error - */ - fetchCollectionInfo(client, ns, filter, callback) { - const bson = this.bson; - const dbName = databaseNamespace(ns); - - client - .db(dbName) - .listCollections(filter, { - promoteLongs: false, - promoteValues: false - }) - .toArray() - .then( - collections => { - const info = collections.length > 0 ? bson.serialize(collections[0]) : null; - return callback(null, info); - }, - err => { - callback(err, null); - } - ); - } - - /** - * @ignore - * Calls to the mongocryptd to provide markings for a command. - * Exposed for testing purposes. Do not directly invoke. - * @param {MongoClient} client A MongoClient connected to a mongocryptd - * @param {string} ns The namespace (database.collection) the command is being executed on - * @param {object} command The command to execute. - * @param {StateMachine~markCommandCallback} callback Invoked with the serialized and marked bson command, or with an error - * @returns {void} - */ - markCommand(client, ns, command, callback) { - const bson = this.bson; - const options = { promoteLongs: false, promoteValues: false }; - const dbName = databaseNamespace(ns); - const rawCommand = bson.deserialize(command, options); - - client - .db(dbName) - .command(rawCommand, options) - .then( - response => { - return callback(null, bson.serialize(response, this.options)); - }, - err => { - callback(err, null); - } - ); - } - - /** - * @ignore - * Requests keys from the keyVault collection on the topology. - * Exposed for testing purposes. Do not directly invoke. - * @param {MongoClient} client A MongoClient connected to the topology - * @param {string} keyVaultNamespace The namespace (database.collection) of the keyVault Collection - * @param {object} filter The filter for the find query against the keyVault Collection - * @param {StateMachine~fetchKeysCallback} callback Invoked with the found keys, or with an error - * @returns {void} - */ - fetchKeys(client, keyVaultNamespace, filter, callback) { - const bson = this.bson; - const dbName = databaseNamespace(keyVaultNamespace); - const collectionName = collectionNamespace(keyVaultNamespace); - filter = bson.deserialize(filter); - - client - .db(dbName) - .collection(collectionName, { readConcern: { level: 'majority' } }) - .find(filter) - .toArray() - .then( - keys => { - return callback(null, keys); - }, - err => { - callback(err, null); - } - ); - } - } - - return { StateMachine }; -}; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/package-lock.json b/ext/libmongocrypt/libmongocrypt/bindings/node/package-lock.json deleted file mode 100644 index 934fda3..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/package-lock.json +++ /dev/null @@ -1,15302 +0,0 @@ -{ - "name": "mongodb-client-encryption", - "version": "2.8.0-alpha.1", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "mongodb-client-encryption", - "version": "2.8.0-alpha.1", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^4.3.0", - "prebuild-install": "^7.1.1", - "socks": "^2.6.1" - }, - "devDependencies": { - "@types/sinon": "^10.0.13", - "@types/sinon-chai": "^3.2.9", - "chai": "^4.3.6", - "chai-subset": "^1.6.0", - "chalk": "^4.1.2", - "clang-format": "^1.6.0", - "dmd-clear": "^0.1.2", - "eslint": "^8.8.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-prettier": "^4.0.0", - "jsdoc-to-markdown": "^7.1.1", - "mocha": "^9.2.0", - "mongodb": "^4.9.0", - "node-gyp": "^9.3.1", - "prebuild": "^11.0.2", - "prettier": "^2.5.1", - "sinon": "^13.0.1", - "sinon-chai": "^3.7.0", - "standard-version": "^9.3.2", - "tar": "^6.1.11", - "tsd": "^0.25.0" - }, - "engines": { - "node": ">=12.9.0" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.186.0", - "gcp-metadata": "^5.2.0", - "mongodb": ">=3.4.0" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "gcp-metadata": { - "optional": true - } - } - }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.16.12", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", - "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", - "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.2.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.3.tgz", - "integrity": "sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.0.0.tgz", - "integrity": "sha512-+shXA2X7KNP7H7qNbQTJ3SA+NQc0pZDSBrdvFSRwF8sAo/ohw+ZQFD8Moc+gnz51+1eRXtEQBpKWPiQ4jsRC/w==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", - "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tsd/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/@tsd/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-70j1vy95LsMvciXWJLrQ9pQaaG1inJJ+gZ/dW/bPdzHUH1VTeSl3BBU6QxqFWh5IjPy6s7xHcUw45R71dw4J3w==", - "dev": true - }, - "node_modules/@types/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", - "dev": true - }, - "node_modules/@types/eslint": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", - "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", - "dev": true - }, - "node_modules/@types/markdown-it": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", - "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", - "dev": true, - "dependencies": { - "@types/linkify-it": "*", - "@types/mdurl": "*" - } - }, - "node_modules/@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", - "dev": true - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.7.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.6.tgz", - "integrity": "sha512-EdxgKRXgYsNITy5mjjXjVE/CS8YENSdhiagGrLqjG0pvA2owgJ6i4l7wy/PFZGC0B1/H20lWKN7ONVDNYDZm7A==", - "dev": true - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/sinon": { - "version": "10.0.13", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", - "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", - "dev": true, - "dependencies": { - "@types/sinonjs__fake-timers": "*" - } - }, - "node_modules/@types/sinon-chai": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.9.tgz", - "integrity": "sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ==", - "dev": true, - "dependencies": { - "@types/chai": "*", - "@types/sinon": "*" - } - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", - "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", - "dev": true - }, - "node_modules/@types/webidl-conversions": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", - "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==", - "dev": true - }, - "node_modules/@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/webidl-conversions": "*" - } - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", - "dev": true - }, - "node_modules/after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "depd": "^2.0.0", - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "engines": { - "node": ">=0.4.2" - } - }, - "node_modules/ansi": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", - "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", - "dev": true - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escape-sequences": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", - "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", - "dev": true, - "dependencies": { - "array-back": "^3.0.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ansi-escape-sequences/node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", - "dev": true, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", - "dev": true - }, - "node_modules/array-index": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-index/-/array-index-1.0.0.tgz", - "integrity": "sha1-7FanSe4QPk4Ix5C5w1PfFgVbl/k=", - "dev": true, - "dependencies": { - "debug": "^2.2.0", - "es6-symbol": "^3.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/array-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/array-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.1.tgz", - "integrity": "sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.1" - } - }, - "node_modules/block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "dependencies": { - "inherits": "~2.0.0" - }, - "engines": { - "node": "0.4 || >=0.5.8" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/bson": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", - "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", - "dev": true, - "dependencies": { - "buffer": "^5.6.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-from": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", - "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==", - "dev": true - }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", - "dev": true - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cache-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", - "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", - "dev": true, - "dependencies": { - "array-back": "^4.0.1", - "fs-then-native": "^2.0.0", - "mkdirp2": "^1.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cache-point/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chai-subset": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/chai-subset/-/chai-subset-1.6.0.tgz", - "integrity": "sha1-pdDKFOMpp5WW7XAFi2ZGvWmIz+k=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/clang-format": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.6.0.tgz", - "integrity": "sha512-W3/L7fWkA8DoLkz9UGjrRnNi+J5a5TuS2HDLqk6WsicpOzb66MBu4eY/EcXhicHriVnAXWQVyk5/VeHWY6w4ow==", - "dev": true, - "dependencies": { - "async": "^1.5.2", - "glob": "^7.0.0", - "resolve": "^1.1.6" - }, - "bin": { - "check-clang-format": "bin/check-clang-format.js", - "clang-format": "index.js", - "git-clang-format": "bin/git-clang-format" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cmake-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-5.2.0.tgz", - "integrity": "sha512-/HLhzoBEOLKGdE1FLwH5ggzRt67AWTb4IErg4rm+bTC+R0DKUobojDyp17dSswDVPosdoPmHXjKxbJiyBZfQeg==", - "dev": true, - "dependencies": { - "bluebird": "^3", - "debug": "^4", - "fs-extra": "^5.0.0", - "is-iojs": "^1.0.1", - "lodash": "^4", - "memory-stream": "0", - "npmlog": "^1.2.0", - "rc": "^1.2.7", - "request": "^2.54.0", - "semver": "^5.0.3", - "splitargs": "0", - "tar": "^4", - "traceur": "0.0.x", - "unzipper": "^0.8.13", - "url-join": "0", - "which": "^1.0.9", - "yargs": "^3.6.0" - }, - "bin": { - "cmake-js": "bin/cmake-js" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/cmake-js/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cmake-js/node_modules/are-we-there-yet": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.0.6.tgz", - "integrity": "sha1-otKMkxAqpsyWJFomy5VN4G7FPww=", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.0 || ^1.1.13" - } - }, - "node_modules/cmake-js/node_modules/camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cmake-js/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/cmake-js/node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/cmake-js/node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "dependencies": { - "minipass": "^2.6.0" - } - }, - "node_modules/cmake-js/node_modules/gauge": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", - "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", - "dev": true, - "dependencies": { - "ansi": "^0.3.0", - "has-unicode": "^2.0.0", - "lodash.pad": "^4.1.0", - "lodash.padend": "^4.1.0", - "lodash.padstart": "^4.1.0" - } - }, - "node_modules/cmake-js/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cmake-js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/cmake-js/node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/cmake-js/node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "dependencies": { - "minipass": "^2.9.0" - } - }, - "node_modules/cmake-js/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/cmake-js/node_modules/npmlog": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-1.2.1.tgz", - "integrity": "sha1-KOe+YZYJtT960d0wChDWTXFiaLY=", - "dev": true, - "dependencies": { - "ansi": "~0.3.0", - "are-we-there-yet": "~1.0.0", - "gauge": "~1.2.0" - } - }, - "node_modules/cmake-js/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/cmake-js/node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/cmake-js/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/cmake-js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/cmake-js/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/cmake-js/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cmake-js/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cmake-js/node_modules/tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "dev": true, - "dependencies": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - }, - "engines": { - "node": ">=4.5" - } - }, - "node_modules/cmake-js/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/cmake-js/node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cmake-js/node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/cmake-js/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/cmake-js/node_modules/yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "dev": true, - "dependencies": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collect-all": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", - "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", - "dev": true, - "dependencies": { - "stream-connect": "^1.0.2", - "stream-via": "^1.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "dev": true, - "dependencies": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-args/node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/command-line-args/node_modules/typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/command-line-tool": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", - "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", - "dev": true, - "dependencies": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "command-line-args": "^5.0.0", - "command-line-usage": "^4.1.0", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-tool/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/command-line-usage": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", - "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", - "dev": true, - "dependencies": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "table-layout": "^0.4.2", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/common-sequence": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", - "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "engines": [ - "node >= 6.0" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/config-master": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", - "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", - "dev": true, - "dependencies": { - "walk-back": "^2.0.1" - } - }, - "node_modules/config-master/node_modules/walk-back": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", - "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "node_modules/conventional-changelog": { - "version": "3.1.24", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", - "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", - "dev": true, - "dependencies": { - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-atom": "^2.0.8", - "conventional-changelog-codemirror": "^2.0.8", - "conventional-changelog-conventionalcommits": "^4.5.0", - "conventional-changelog-core": "^4.2.1", - "conventional-changelog-ember": "^2.0.9", - "conventional-changelog-eslint": "^3.0.9", - "conventional-changelog-express": "^2.0.6", - "conventional-changelog-jquery": "^3.0.11", - "conventional-changelog-jshint": "^2.0.9", - "conventional-changelog-preset-loader": "^2.3.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-atom": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", - "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-codemirror": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", - "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-config-spec": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", - "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", - "dev": true - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", - "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", - "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", - "dev": true, - "dependencies": { - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-parser": "^3.2.0", - "dateformat": "^3.0.0", - "get-pkg-repo": "^4.0.0", - "git-raw-commits": "^2.0.8", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.1", - "lodash": "^4.17.15", - "normalize-package-data": "^3.0.0", - "q": "^1.5.1", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-core/node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/conventional-changelog-ember": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", - "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-eslint": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", - "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-express": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", - "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-jquery": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", - "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", - "dev": true, - "dependencies": { - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-jshint": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", - "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-preset-loader": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", - "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-writer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", - "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", - "dev": true, - "dependencies": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-changelog-writer": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-writer/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/conventional-changelog-writer/node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/conventional-commits-filter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", - "dev": true, - "dependencies": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", - "dev": true, - "dependencies": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-parser/node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/conventional-recommended-bump": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", - "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", - "dev": true, - "dependencies": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.7", - "conventional-commits-parser": "^3.2.0", - "git-raw-commits": "^2.0.8", - "git-semver-tags": "^4.1.1", - "meow": "^8.0.0", - "q": "^1.5.1" - }, - "bin": { - "conventional-recommended-bump": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-libc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.0.tgz", - "integrity": "sha512-S55LzUl8HUav8l9E2PBTlC5PAJrHK7tkM+XXFGD+fbsbkTzhCpG6K05LxJcUOEWzMa4v6ptcMZ9s3fOdJDu0Zw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dir-glob/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dmd": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.1.0.tgz", - "integrity": "sha512-0zQIJ873gay1scCTFZvHPWM9mVJBnaylB2NQDI8O9u8O32m00Jb6uxDKexZm8hjTRM7RiWe0FJ32pExHoXdwoQ==", - "dev": true, - "dependencies": { - "array-back": "^6.2.2", - "cache-point": "^2.0.0", - "common-sequence": "^2.0.2", - "file-set": "^4.0.2", - "handlebars": "^4.7.7", - "marked": "^4.0.12", - "object-get": "^2.1.1", - "reduce-flatten": "^3.0.1", - "reduce-unique": "^2.0.1", - "reduce-without": "^1.0.1", - "test-value": "^3.0.0", - "walk-back": "^5.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dmd-clear": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dmd-clear/-/dmd-clear-0.1.2.tgz", - "integrity": "sha1-8GHFsHKya6IxZN1ajAvIZogzvhI=", - "dev": true - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotgitignore": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", - "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/dotgitignore/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotgitignore/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "dependencies": { - "readable-stream": "~1.1.9" - } - }, - "node_modules/duplexer2/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/each-series-async": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/each-series-async/-/each-series-async-1.0.1.tgz", - "integrity": "sha512-G4zip/Ewpwr6JQxW7+2RNgkPd09h/UNec5UlvA/xKwl4qf5blyBNK6a/zjQc3MojgsxaOb93B9v3T92QU6IMVg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", - "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.0.5", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.2.0", - "espree": "^9.3.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-formatter-pretty": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-formatter-pretty/-/eslint-formatter-pretty-4.1.0.tgz", - "integrity": "sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==", - "dev": true, - "dependencies": { - "@types/eslint": "^7.2.13", - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "eslint-rule-docs": "^1.1.5", - "log-symbols": "^4.0.0", - "plur": "^4.0.0", - "string-width": "^4.2.0", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-rule-docs": { - "version": "1.1.235", - "resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz", - "integrity": "sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==", - "dev": true - }, - "node_modules/eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", - "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/espree": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", - "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", - "dev": true, - "dependencies": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execspawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/execspawn/-/execspawn-1.0.1.tgz", - "integrity": "sha1-gob53efOzeeQX73ATiTzaPI/jaY=", - "dev": true, - "dependencies": { - "util-extend": "^1.0.1" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", - "dev": true, - "dependencies": { - "type": "^2.5.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-set": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", - "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", - "dev": true, - "dependencies": { - "array-back": "^5.0.0", - "glob": "^7.1.6" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/file-set/node_modules/array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, - "dependencies": { - "array-back": "^3.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-replace/node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs-access": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", - "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true, - "dependencies": { - "null-check": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, - "node_modules/fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-then-native": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", - "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/fstream/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/fstream/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/gauge": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.0.tgz", - "integrity": "sha512-F8sU45yQpjQjxKkm1UOAhf0U/O0aFt//Fl7hsrNVto+patMHjs7dPI9mFOGUKbhrgKm0S3EjW3scMFuQmWSROw==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", - "dev": true, - "dependencies": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - }, - "bin": { - "get-pkg-repo": "src/cli.js" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-pkg-repo/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/get-pkg-repo/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/get-pkg-repo/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/get-pkg-repo/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/get-pkg-repo/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/ghreleases": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/ghreleases/-/ghreleases-3.0.2.tgz", - "integrity": "sha512-QiR9mIYvRG7hd8JuQYoxeBNOelVuTp2DpdiByRywbCDBSJufK9Vq7VuhD8B+5uviMxZx2AEkCzye61Us9gYgnw==", - "dev": true, - "dependencies": { - "after": "~0.8.1", - "ghrepos": "~2.1.0", - "ghutils": "~3.2.0", - "lodash.uniq": "^4.5.0", - "simple-mime": "~0.1.0", - "url-template": "~2.0.6" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ghrepos": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ghrepos/-/ghrepos-2.1.0.tgz", - "integrity": "sha512-6GM0ohSDTAv7xD6GsKfxJiV/CajoofRyUwu0E8l29d1o6lFAUxmmyMP/FH33afA20ZrXzxxcTtN6TsYvudMoAg==", - "dev": true, - "dependencies": { - "ghutils": "~3.2.0" - } - }, - "node_modules/ghutils": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/ghutils/-/ghutils-3.2.6.tgz", - "integrity": "sha512-WpYHgLQkqU7Cv147wKUEThyj6qKHCdnAG2CL9RRsRQImVdLGdVqblJ3JUnj3ToQwgm1ALPS+FXgR0448AgGPUg==", - "dev": true, - "dependencies": { - "jsonist": "~2.1.0", - "xtend": "~4.0.1" - } - }, - "node_modules/git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", - "dev": true, - "dependencies": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/git-raw-commits/node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", - "dev": true, - "dependencies": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/git-semver-tags": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", - "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", - "dev": true, - "dependencies": { - "meow": "^8.0.0", - "semver": "^6.0.0" - }, - "bin": { - "git-semver-tags": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/git-semver-tags/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", - "dev": true, - "dependencies": { - "ini": "^1.3.2" - } - }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "node_modules/graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/hyperquest": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/hyperquest/-/hyperquest-2.1.3.tgz", - "integrity": "sha512-fUuDOrB47PqNK/BAMOS13v41UoaqIxqSLHX6CAbOD7OfT+/GCWO1/vPLfTNutOeXrv1ikuaZ3yux+33Z9vh+rw==", - "dev": true, - "dependencies": { - "buffer-from": "^0.1.1", - "duplexer2": "~0.0.2", - "through2": "~0.6.3" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "node_modules/irregular-plurals": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.4.0.tgz", - "integrity": "sha512-YXxECO/W6N9aMBVKMKKZ8TXESgq7EFrp3emCGGUcrYY1cgJIeZjoB75MTu8qi+NAKntS9NwPU8VdcQ3r6E6aWQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-iojs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-iojs/-/is-iojs-1.1.0.tgz", - "integrity": "sha1-TBEDO11dlNbqs3dd7cm+fQCDJfE=", - "dev": true - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", - "dev": true, - "dependencies": { - "text-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, - "dependencies": { - "xmlcreate": "^2.0.4" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/jsdoc": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.10.tgz", - "integrity": "sha512-IdQ8ppSo5LKZ9o3M+LKIIK8i00DIe5msDvG3G81Km+1dhy0XrOWD0Ji8H61ElgyEj/O9KRLokgKbAM9XX9CJAg==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.9.4", - "@types/markdown-it": "^12.2.3", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.2", - "klaw": "^4.0.1", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.4.1", - "marked": "^4.0.10", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.13.2" - }, - "bin": { - "jsdoc": "jsdoc.js" - }, - "engines": { - "node": ">=8.15.0" - } - }, - "node_modules/jsdoc-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.1.1.tgz", - "integrity": "sha512-0pkuPCzVXiqsDAsVrNFXCkHzlyNepBIDVtwwehry4RJAnZmXtlAz7rh8F9FRz53u3NeynGbex+bpYWwi8lE66A==", - "dev": true, - "dependencies": { - "array-back": "^6.2.2", - "cache-point": "^2.0.0", - "collect-all": "^1.0.4", - "file-set": "^4.0.2", - "fs-then-native": "^2.0.0", - "jsdoc": "^3.6.10", - "object-to-spawn-args": "^2.0.1", - "temp-path": "^1.0.0", - "walk-back": "^5.1.0" - }, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/jsdoc-parse": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.1.0.tgz", - "integrity": "sha512-n/hDGQJa69IBun1yZAjqzV4gVR41+flZ3bIlm9fKvNe2Xjsd1/+zCo2+R9ls8LxtePgIWbpA1jU7xkB2lRdLLg==", - "dev": true, - "dependencies": { - "array-back": "^6.2.2", - "lodash.omit": "^4.5.0", - "lodash.pick": "^4.4.0", - "reduce-extract": "^1.0.0", - "sort-array": "^4.1.4", - "test-value": "^3.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jsdoc-to-markdown": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.1.tgz", - "integrity": "sha512-CI86d63xAVNO+ENumWwmJ034lYe5iGU5GwjtTA11EuphP9tpnoi4hrKgR/J8uME0D+o4KUpVfwX1fjZhc8dEtg==", - "dev": true, - "dependencies": { - "array-back": "^6.2.2", - "command-line-tool": "^0.8.0", - "config-master": "^3.1.0", - "dmd": "^6.1.0", - "jsdoc-api": "^7.1.1", - "jsdoc-parse": "^6.1.0", - "walk-back": "^5.1.0" - }, - "bin": { - "jsdoc2md": "bin/cli.js" - }, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/jsdoc/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/jsonist/-/jsonist-2.1.2.tgz", - "integrity": "sha512-8yqmWJAC2VaYoSKQAbsfgCpGY5o/1etWzx6ZxaZrC4iGaHrHUZEo+a2MyF8w+2uTavTlHdLWaZUoR19UfBstxQ==", - "dev": true, - "dependencies": { - "bl": "~3.0.0", - "hyperquest": "~2.1.3", - "json-stringify-safe": "~5.0.1", - "xtend": "~4.0.1" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true, - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klaw": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.0.1.tgz", - "integrity": "sha512-pgsE40/SvC7st04AHiISNewaIMUbY5V/K8b21ekiPiFoYs/EYSdsGa+FJArB1d441uq4Q8zZyIxvAzkGNlBdRw==", - "dev": true, - "engines": { - "node": ">=14.14.0" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "node_modules/lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", - "dev": true - }, - "node_modules/lodash.pad": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", - "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", - "dev": true - }, - "node_modules/lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", - "dev": true - }, - "node_modules/lodash.padstart": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", - "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", - "dev": true - }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/loupe": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", - "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it-anchor": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.4.1.tgz", - "integrity": "sha512-sLODeRetZ/61KkKLJElaU3NuU2z7MhXf12Ml1WJMSdwpngeofneCRF+JBbat8HiSqhniOMuTemXMrsI7hA6XyA==", - "dev": true, - "peerDependencies": { - "@types/markdown-it": "*", - "markdown-it": "*" - } - }, - "node_modules/marked": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", - "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "dev": true, - "optional": true - }, - "node_modules/memory-stream": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-0.0.3.tgz", - "integrity": "sha1-6+jdHDuLw4wOeUHp3dWuvmtN6D8=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.26-2" - } - }, - "node_modules/memory-stream/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/memory-stream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/meow/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/meow/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minipass": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", - "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, - "node_modules/mkdirp2": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", - "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", - "dev": true - }, - "node_modules/mocha": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", - "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "4.2.1", - "ms": "2.1.3", - "nanoid": "3.3.1", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", - "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mongodb": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.9.0.tgz", - "integrity": "sha512-tJJEFJz7OQTQPZeVHZJIeSOjMRqc5eSyXTt86vSQENEErpkiG7279tM/GT5AVZ7TgXNh9HQxoa2ZkbrANz5GQw==", - "dev": true, - "dependencies": { - "bson": "^4.7.0", - "denque": "^2.1.0", - "mongodb-connection-string-url": "^2.5.3", - "socks": "^2.7.0" - }, - "engines": { - "node": ">=12.9.0" - }, - "optionalDependencies": { - "saslprep": "^1.0.3" - } - }, - "node_modules/mongodb-connection-string-url": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.3.tgz", - "integrity": "sha512-f+/WsED+xF4B74l3k9V/XkTVj5/fxFH2o5ToKXd8Iyi5UhM+sO9u0Ape17Mvl/GkZaFtM0HQnzAG5OTmhKw+tQ==", - "dev": true, - "dependencies": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/nise": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", - "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": ">=5", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/node-abi": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.7.0.tgz", - "integrity": "sha512-3J+U4CvxVNEk9+lGdJkmYbN8cIN0HMTDT9R0ezX7pmp7aD6BaKsfAHwVn3IvVg6pYIRUuQ+gHW1eawrvywnSQQ==", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" - }, - "node_modules/node-gyp": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", - "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" - } - }, - "node_modules/node-ninja": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/node-ninja/-/node-ninja-1.0.2.tgz", - "integrity": "sha1-IKCeV7kuLfWRmT1L8JisPnJwYrY=", - "dev": true, - "dependencies": { - "fstream": "^1.0.0", - "glob": "3 || 4 || 5 || 6 || 7", - "graceful-fs": "^4.1.2", - "minimatch": "3", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2", - "osenv": "0", - "path-array": "^1.0.0", - "request": "2", - "rimraf": "2", - "semver": "2.x || 3.x || 4 || 5", - "tar": "^2.0.0", - "which": "1" - }, - "bin": { - "node-ninja": "bin/node-ninja.js" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/node-ninja/node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/node-ninja/node_modules/gauge": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", - "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", - "dev": true, - "dependencies": { - "ansi": "^0.3.0", - "has-unicode": "^2.0.0", - "lodash.pad": "^4.1.0", - "lodash.padend": "^4.1.0", - "lodash.padstart": "^4.1.0" - } - }, - "node_modules/node-ninja/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/node-ninja/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/node-ninja/node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/node-ninja/node_modules/npmlog": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", - "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", - "dev": true, - "dependencies": { - "ansi": "~0.3.1", - "are-we-there-yet": "~1.1.2", - "gauge": "~1.2.5" - } - }, - "node_modules/node-ninja/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/node-ninja/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/node-ninja/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/node-ninja/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/node-ninja/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/node-ninja/node_modules/tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "deprecated": "This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.", - "dev": true, - "dependencies": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, - "node_modules/node-ninja/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/noop-logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", - "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", - "dev": true - }, - "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-path": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", - "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", - "dev": true, - "dependencies": { - "which": "^1.2.10" - }, - "bin": { - "npm-path": "bin/npm-path" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm-path/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/npm-which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", - "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", - "dev": true, - "dependencies": { - "commander": "^2.9.0", - "npm-path": "^2.0.2", - "which": "^1.2.10" - }, - "bin": { - "npm-which": "bin/npm-which.js" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/npm-which/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/npmlog": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.0.tgz", - "integrity": "sha512-03ppFRGlsyUaQFbGC2C8QWJN/C/K7PsfyD9aQdhVKAQIH4sQBc8WASqFBP7O+Ut4d2oo5LoeoboB3cGdBZSp6Q==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.0", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/null-check": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", - "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nw-gyp": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/nw-gyp/-/nw-gyp-3.6.5.tgz", - "integrity": "sha512-vYrOIYJEKpq9CfaHuiqEjV1rBYgr6uaUrPhPRiznb91LujkAUqGhQ5QqDC1bLdd+zo9jf2H0Zkl2M5zQB7+CuQ==", - "dev": true, - "dependencies": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "2", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "bin": { - "nw-gyp": "bin/nw-gyp.js" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/nw-gyp/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nw-gyp/node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "node_modules/nw-gyp/node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/nw-gyp/node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/nw-gyp/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nw-gyp/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/nw-gyp/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/nw-gyp/node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/nw-gyp/node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/nw-gyp/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/nw-gyp/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/nw-gyp/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/nw-gyp/node_modules/semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/nw-gyp/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/nw-gyp/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nw-gyp/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nw-gyp/node_modules/tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "deprecated": "This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.", - "dev": true, - "dependencies": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, - "node_modules/nw-gyp/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-get": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", - "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", - "dev": true - }, - "node_modules/object-to-spawn-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", - "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-array": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-array/-/path-array-1.0.1.tgz", - "integrity": "sha1-fi8PNfB6IBUSK4aLfqwOssT+wnE=", - "dev": true, - "dependencies": { - "array-index": "^1.0.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/plur": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", - "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", - "dev": true, - "dependencies": { - "irregular-plurals": "^3.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/prebuild": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/prebuild/-/prebuild-11.0.3.tgz", - "integrity": "sha512-0synbTNdYD9nkVFtVl0nbslM6AefnKRcvyvtDwv6qswh4gYCbdWGmir4G7YPPDa3VmKCZADVBYnkqNI3qKJy5Q==", - "dev": true, - "dependencies": { - "cmake-js": "~5.2.0", - "detect-libc": "^2.0.0", - "each-series-async": "^1.0.1", - "execspawn": "^1.0.1", - "ghreleases": "^3.0.2", - "github-from-package": "0.0.0", - "glob": "^7.1.6", - "minimist": "^1.1.2", - "mkdirp": "^0.5.1", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.0.0", - "node-gyp": "^6.0.1", - "node-ninja": "^1.0.1", - "noop-logger": "^0.1.0", - "npm-which": "^3.0.1", - "npmlog": "^4.0.1", - "nw-gyp": "^3.6.3", - "rc": "^1.0.3", - "run-waterfall": "^1.1.6", - "tar-stream": "^2.1.0" - }, - "bin": { - "prebuild": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prebuild/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prebuild/node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "node_modules/prebuild/node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/prebuild/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/prebuild/node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "dependencies": { - "minipass": "^2.6.0" - } - }, - "node_modules/prebuild/node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/prebuild/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prebuild/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/prebuild/node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/prebuild/node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "dependencies": { - "minipass": "^2.9.0" - } - }, - "node_modules/prebuild/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/prebuild/node_modules/node-gyp": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-6.1.0.tgz", - "integrity": "sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "mkdirp": "^0.5.1", - "nopt": "^4.0.1", - "npmlog": "^4.1.2", - "request": "^2.88.0", - "rimraf": "^2.6.3", - "semver": "^5.7.1", - "tar": "^4.4.12", - "which": "^1.3.1" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/prebuild/node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "dev": true, - "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/prebuild/node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/prebuild/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/prebuild/node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/prebuild/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/prebuild/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/prebuild/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/prebuild/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/prebuild/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prebuild/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prebuild/node_modules/tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "dev": true, - "dependencies": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - }, - "engines": { - "node": ">=4.5" - } - }, - "node_modules/prebuild/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/prebuild/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true, - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reduce-extract": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", - "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", - "dev": true, - "dependencies": { - "test-value": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-extract/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/reduce-extract/node_modules/test-value": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", - "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", - "dev": true, - "dependencies": { - "array-back": "^1.0.2", - "typical": "^2.4.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-flatten": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", - "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/reduce-unique": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", - "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/reduce-without": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", - "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", - "dev": true, - "dependencies": { - "test-value": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-without/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/reduce-without/node_modules/test-value": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", - "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", - "dev": true, - "dependencies": { - "array-back": "^1.0.3", - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rsvp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", - "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", - "dev": true, - "engines": { - "node": "0.12.* || 4.* || 6.* || >= 7.*" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/run-waterfall": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/run-waterfall/-/run-waterfall-1.1.7.tgz", - "integrity": "sha512-iFPgh7SatHXOG1ClcpdwHI63geV3Hc/iL6crGSyBlH2PY7Rm/za+zoKz6FfY/Qlw5K7JwSol8pseO8fN6CMhhQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "dev": true, - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/simple-mime": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/simple-mime/-/simple-mime-0.1.0.tgz", - "integrity": "sha1-lfUXxPRm18/1YacfydqyWW6p7y4=", - "dev": true, - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/sinon": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.1.tgz", - "integrity": "sha512-8yx2wIvkBjIq/MGY1D9h1LMraYW+z1X0mb648KZnKSdvLasvDu7maa0dFaNYdTDczFgbjNw2tOmWdTk9saVfwQ==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^9.0.0", - "@sinonjs/samsam": "^6.1.1", - "diff": "^5.0.0", - "nise": "^5.1.1", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon-chai": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "dev": true, - "peerDependencies": { - "chai": "^4.0.0", - "sinon": ">=4.0.0" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", - "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/sort-array": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.4.tgz", - "integrity": "sha512-GVFN6Y1sHKrWaSYOJTk9093ZnrBMc9sP3nuhANU44S4xg3rE6W5Z5WyamuT8VpMBbssnetx5faKCua0LEmUnSw==", - "dev": true, - "dependencies": { - "array-back": "^5.0.0", - "typical": "^6.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sort-array/node_modules/array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/sort-array/node_modules/typical": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", - "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", - "integrity": "sha1-6lo5AKHByyUJagrozFwrSxDe09w=", - "dev": true, - "dependencies": { - "source-map": "0.1.32" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.1.32", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", - "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", - "dev": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "dev": true, - "optional": true, - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/splitargs": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/splitargs/-/splitargs-0.0.7.tgz", - "integrity": "sha1-/p965lc3GzOxDLgNoUPPgknPazs=", - "dev": true - }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/standard-version": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", - "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "conventional-changelog": "3.1.24", - "conventional-changelog-config-spec": "2.1.0", - "conventional-changelog-conventionalcommits": "4.6.1", - "conventional-recommended-bump": "6.1.0", - "detect-indent": "^6.0.0", - "detect-newline": "^3.1.0", - "dotgitignore": "^2.1.0", - "figures": "^3.1.0", - "find-up": "^5.0.0", - "fs-access": "^1.0.1", - "git-semver-tags": "^4.0.0", - "semver": "^7.1.1", - "stringify-package": "^1.0.1", - "yargs": "^16.0.0" - }, - "bin": { - "standard-version": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/standard-version/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/standard-version/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/standard-version/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/standard-version/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/standard-version/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/standard-version/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/standard-version/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/stream-connect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", - "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", - "dev": true, - "dependencies": { - "array-back": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-connect/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/stream-via": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", - "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/stringify-package": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", - "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", - "dev": true - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/table-layout": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", - "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", - "dev": true, - "dependencies": { - "array-back": "^2.0.0", - "deep-extend": "~0.6.0", - "lodash.padend": "^4.6.1", - "typical": "^2.6.1", - "wordwrapjs": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", - "dev": true - }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-fs/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-stream/node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/temp-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", - "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", - "dev": true - }, - "node_modules/test-value": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", - "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", - "dev": true, - "dependencies": { - "array-back": "^2.0.0", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/test-value/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "dependencies": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/traceur": { - "version": "0.0.111", - "resolved": "https://registry.npmjs.org/traceur/-/traceur-0.0.111.tgz", - "integrity": "sha1-wE3nTRRpbDNzQn3k/Ajsr5E/w6E=", - "dev": true, - "dependencies": { - "commander": "2.9.x", - "glob": "5.0.x", - "rsvp": "^3.0.13", - "semver": "^4.3.3", - "source-map-support": "~0.2.8" - }, - "bin": { - "traceur": "traceur" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/traceur/node_modules/commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "dependencies": { - "graceful-readlink": ">= 1.0.0" - }, - "engines": { - "node": ">= 0.6.x" - } - }, - "node_modules/traceur/node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/traceur/node_modules/semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsd": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.25.0.tgz", - "integrity": "sha512-liUlvKtsdr+70XEZP/kkF6U8+Q9URZi4Pw58ih7a9x3kjJblG8rdVgvG62xcvkgRva1q3yWX5qAxfYZuYiC5CA==", - "dev": true, - "dependencies": { - "@tsd/typescript": "~4.9.3", - "eslint-formatter-pretty": "^4.1.0", - "globby": "^11.0.1", - "meow": "^9.0.0", - "path-exists": "^4.0.0", - "read-pkg-up": "^7.0.0" - }, - "bin": { - "tsd": "dist/cli.js" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/tsd/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsd/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/tsd/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsd/node_modules/meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tsd/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tsd/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsd/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tsd/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsd/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tsd/node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsd/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/tsd/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsd/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/tsd/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/uglify-js": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.0.tgz", - "integrity": "sha512-x+xdeDWq7FiORDvyIJ0q/waWd4PhjBNOm5dQUOq2AKC0IEjxOS66Ha9tctiVDGcRQuh69K7fgU5oRuTK4cysSg==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/underscore": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.2.tgz", - "integrity": "sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g==", - "dev": true - }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unzipper": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.8.14.tgz", - "integrity": "sha512-8rFtE7EP5ssOwGpN2dt1Q4njl0N1hUXJ7sSPz0leU2hRdq6+pra57z4YPBlVqm40vcgv6ooKZEAx48fMTv9x4w==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "~1.0.10", - "listenercount": "~1.0.1", - "readable-stream": "~2.1.5", - "setimmediate": "~1.0.4" - } - }, - "node_modules/unzipper/node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "node_modules/unzipper/node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/unzipper/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/unzipper/node_modules/process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "node_modules/unzipper/node_modules/readable-stream": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", - "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true, - "dependencies": { - "buffer-shims": "^1.0.0", - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/unzipper/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-join": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", - "integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g=", - "dev": true - }, - "node_modules/url-template": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/util-extend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", - "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=", - "dev": true - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/walk-back": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", - "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", - "dev": true, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", - "dev": true, - "bin": { - "window-size": "cli.js" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "node_modules/wordwrapjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", - "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", - "dev": true, - "dependencies": { - "reduce-flatten": "^1.0.1", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/wordwrapjs/node_modules/reduce-flatten": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", - "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.16.12", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", - "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", - "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.2.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - } - } - }, - "@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.3.tgz", - "integrity": "sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", - "dev": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "requires": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - } - }, - "@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.0.0.tgz", - "integrity": "sha512-+shXA2X7KNP7H7qNbQTJ3SA+NQc0pZDSBrdvFSRwF8sAo/ohw+ZQFD8Moc+gnz51+1eRXtEQBpKWPiQ4jsRC/w==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sinonjs/samsam": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz", - "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "@tsd/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/@tsd/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-70j1vy95LsMvciXWJLrQ9pQaaG1inJJ+gZ/dW/bPdzHUH1VTeSl3BBU6QxqFWh5IjPy6s7xHcUw45R71dw4J3w==", - "dev": true - }, - "@types/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", - "dev": true - }, - "@types/eslint": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz", - "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", - "dev": true - }, - "@types/markdown-it": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", - "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", - "dev": true, - "requires": { - "@types/linkify-it": "*", - "@types/mdurl": "*" - } - }, - "@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", - "dev": true - }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "@types/node": { - "version": "18.7.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.6.tgz", - "integrity": "sha512-EdxgKRXgYsNITy5mjjXjVE/CS8YENSdhiagGrLqjG0pvA2owgJ6i4l7wy/PFZGC0B1/H20lWKN7ONVDNYDZm7A==", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "@types/sinon": { - "version": "10.0.13", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", - "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", - "dev": true, - "requires": { - "@types/sinonjs__fake-timers": "*" - } - }, - "@types/sinon-chai": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.9.tgz", - "integrity": "sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ==", - "dev": true, - "requires": { - "@types/chai": "*", - "@types/sinon": "*" - } - }, - "@types/sinonjs__fake-timers": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", - "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", - "dev": true - }, - "@types/webidl-conversions": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", - "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==", - "dev": true - }, - "@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/webidl-conversions": "*" - } - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", - "dev": true - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "depd": "^2.0.0", - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", - "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", - "dev": true - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escape-sequences": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", - "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", - "dev": true, - "requires": { - "array-back": "^3.0.1" - }, - "dependencies": { - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true - } - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", - "dev": true - }, - "array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", - "dev": true - }, - "array-index": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-index/-/array-index-1.0.0.tgz", - "integrity": "sha1-7FanSe4QPk4Ix5C5w1PfFgVbl/k=", - "dev": true, - "requires": { - "debug": "^2.2.0", - "es6-symbol": "^3.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.1.tgz", - "integrity": "sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ==", - "dev": true, - "requires": { - "readable-stream": "^3.0.1" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "~2.0.0" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "bson": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", - "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", - "dev": true, - "requires": { - "buffer": "^5.6.0" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", - "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==", - "dev": true - }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true - }, - "buffer-shims": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", - "dev": true - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, - "cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "requires": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "cache-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", - "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", - "dev": true, - "requires": { - "array-back": "^4.0.1", - "fs-then-native": "^2.0.0", - "mkdirp2": "^1.0.4" - }, - "dependencies": { - "array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true - } - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", - "dev": true, - "requires": { - "lodash": "^4.17.15" - } - }, - "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chai-subset": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/chai-subset/-/chai-subset-1.6.0.tgz", - "integrity": "sha1-pdDKFOMpp5WW7XAFi2ZGvWmIz+k=", - "dev": true - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "clang-format": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.6.0.tgz", - "integrity": "sha512-W3/L7fWkA8DoLkz9UGjrRnNi+J5a5TuS2HDLqk6WsicpOzb66MBu4eY/EcXhicHriVnAXWQVyk5/VeHWY6w4ow==", - "dev": true, - "requires": { - "async": "^1.5.2", - "glob": "^7.0.0", - "resolve": "^1.1.6" - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "cmake-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-5.2.0.tgz", - "integrity": "sha512-/HLhzoBEOLKGdE1FLwH5ggzRt67AWTb4IErg4rm+bTC+R0DKUobojDyp17dSswDVPosdoPmHXjKxbJiyBZfQeg==", - "dev": true, - "requires": { - "bluebird": "^3", - "debug": "^4", - "fs-extra": "^5.0.0", - "is-iojs": "^1.0.1", - "lodash": "^4", - "memory-stream": "0", - "npmlog": "^1.2.0", - "rc": "^1.2.7", - "request": "^2.54.0", - "semver": "^5.0.3", - "splitargs": "0", - "tar": "^4", - "traceur": "0.0.x", - "unzipper": "^0.8.13", - "url-join": "0", - "which": "^1.0.9", - "yargs": "^3.6.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "are-we-there-yet": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.0.6.tgz", - "integrity": "sha1-otKMkxAqpsyWJFomy5VN4G7FPww=", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.0 || ^1.1.13" - } - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "gauge": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", - "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", - "dev": true, - "requires": { - "ansi": "^0.3.0", - "has-unicode": "^2.0.0", - "lodash.pad": "^4.1.0", - "lodash.padend": "^4.1.0", - "lodash.padstart": "^4.1.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "npmlog": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-1.2.1.tgz", - "integrity": "sha1-KOe+YZYJtT960d0wChDWTXFiaLY=", - "dev": true, - "requires": { - "ansi": "~0.3.0", - "are-we-there-yet": "~1.0.0", - "gauge": "~1.2.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "dev": true, - "requires": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "dev": true, - "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" - } - } - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collect-all": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", - "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", - "dev": true, - "requires": { - "stream-connect": "^1.0.2", - "stream-via": "^1.0.4" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "dev": true, - "requires": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, - "dependencies": { - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true - }, - "typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true - } - } - }, - "command-line-tool": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", - "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", - "dev": true, - "requires": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "command-line-args": "^5.0.0", - "command-line-usage": "^4.1.0", - "typical": "^2.6.1" - }, - "dependencies": { - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - } - } - }, - "command-line-usage": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", - "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", - "dev": true, - "requires": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "table-layout": "^0.4.2", - "typical": "^2.6.1" - }, - "dependencies": { - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - } - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "common-sequence": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", - "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", - "dev": true - }, - "compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "requires": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - } - } - }, - "config-master": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", - "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", - "dev": true, - "requires": { - "walk-back": "^2.0.1" - }, - "dependencies": { - "walk-back": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", - "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", - "dev": true - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "conventional-changelog": { - "version": "3.1.24", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", - "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", - "dev": true, - "requires": { - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-atom": "^2.0.8", - "conventional-changelog-codemirror": "^2.0.8", - "conventional-changelog-conventionalcommits": "^4.5.0", - "conventional-changelog-core": "^4.2.1", - "conventional-changelog-ember": "^2.0.9", - "conventional-changelog-eslint": "^3.0.9", - "conventional-changelog-express": "^2.0.6", - "conventional-changelog-jquery": "^3.0.11", - "conventional-changelog-jshint": "^2.0.9", - "conventional-changelog-preset-loader": "^2.3.4" - } - }, - "conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, - "requires": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - } - }, - "conventional-changelog-atom": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", - "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", - "dev": true, - "requires": { - "q": "^1.5.1" - } - }, - "conventional-changelog-codemirror": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", - "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", - "dev": true, - "requires": { - "q": "^1.5.1" - } - }, - "conventional-changelog-config-spec": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", - "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", - "dev": true - }, - "conventional-changelog-conventionalcommits": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", - "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", - "dev": true, - "requires": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - } - }, - "conventional-changelog-core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", - "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", - "dev": true, - "requires": { - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-parser": "^3.2.0", - "dateformat": "^3.0.0", - "get-pkg-repo": "^4.0.0", - "git-raw-commits": "^2.0.8", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.1", - "lodash": "^4.17.15", - "normalize-package-data": "^3.0.0", - "q": "^1.5.1", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^4.0.0" - }, - "dependencies": { - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "requires": { - "readable-stream": "3" - } - } - } - }, - "conventional-changelog-ember": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", - "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", - "dev": true, - "requires": { - "q": "^1.5.1" - } - }, - "conventional-changelog-eslint": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", - "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", - "dev": true, - "requires": { - "q": "^1.5.1" - } - }, - "conventional-changelog-express": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", - "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", - "dev": true, - "requires": { - "q": "^1.5.1" - } - }, - "conventional-changelog-jquery": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", - "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", - "dev": true, - "requires": { - "q": "^1.5.1" - } - }, - "conventional-changelog-jshint": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", - "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", - "dev": true, - "requires": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - } - }, - "conventional-changelog-preset-loader": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", - "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", - "dev": true - }, - "conventional-changelog-writer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", - "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", - "dev": true, - "requires": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "requires": { - "readable-stream": "3" - } - } - } - }, - "conventional-commits-filter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", - "dev": true, - "requires": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" - } - }, - "conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", - "dev": true, - "requires": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "dependencies": { - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "requires": { - "readable-stream": "3" - } - } - } - }, - "conventional-recommended-bump": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", - "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", - "dev": true, - "requires": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.7", - "conventional-commits-parser": "^3.2.0", - "git-raw-commits": "^2.0.8", - "git-semver-tags": "^4.1.1", - "meow": "^8.0.0", - "q": "^1.5.1" - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true - }, - "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - } - } - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "requires": { - "mimic-response": "^3.1.0" - } - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "dev": true - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true - }, - "detect-libc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.0.tgz", - "integrity": "sha512-S55LzUl8HUav8l9E2PBTlC5PAJrHK7tkM+XXFGD+fbsbkTzhCpG6K05LxJcUOEWzMa4v6ptcMZ9s3fOdJDu0Zw==" - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - }, - "dependencies": { - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - } - } - }, - "dmd": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.1.0.tgz", - "integrity": "sha512-0zQIJ873gay1scCTFZvHPWM9mVJBnaylB2NQDI8O9u8O32m00Jb6uxDKexZm8hjTRM7RiWe0FJ32pExHoXdwoQ==", - "dev": true, - "requires": { - "array-back": "^6.2.2", - "cache-point": "^2.0.0", - "common-sequence": "^2.0.2", - "file-set": "^4.0.2", - "handlebars": "^4.7.7", - "marked": "^4.0.12", - "object-get": "^2.1.1", - "reduce-flatten": "^3.0.1", - "reduce-unique": "^2.0.1", - "reduce-without": "^1.0.1", - "test-value": "^3.0.0", - "walk-back": "^5.1.0" - } - }, - "dmd-clear": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dmd-clear/-/dmd-clear-0.1.2.tgz", - "integrity": "sha1-8GHFsHKya6IxZN1ajAvIZogzvhI=", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, - "dotgitignore": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", - "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "minimatch": "^3.0.4" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "each-series-async": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/each-series-async/-/each-series-async-1.0.1.tgz", - "integrity": "sha512-G4zip/Ewpwr6JQxW7+2RNgkPd09h/UNec5UlvA/xKwl4qf5blyBNK6a/zjQc3MojgsxaOb93B9v3T92QU6IMVg==", - "dev": true - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", - "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.0.5", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.2.0", - "espree": "^9.3.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - } - }, - "eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true, - "requires": {} - }, - "eslint-formatter-pretty": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-formatter-pretty/-/eslint-formatter-pretty-4.1.0.tgz", - "integrity": "sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==", - "dev": true, - "requires": { - "@types/eslint": "^7.2.13", - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "eslint-rule-docs": "^1.1.5", - "log-symbols": "^4.0.0", - "plur": "^4.0.0", - "string-width": "^4.2.0", - "supports-hyperlinks": "^2.0.0" - } - }, - "eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-rule-docs": { - "version": "1.1.235", - "resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz", - "integrity": "sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==", - "dev": true - }, - "eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", - "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", - "dev": true - }, - "espree": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", - "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", - "dev": true, - "requires": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" - } - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "execspawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/execspawn/-/execspawn-1.0.1.tgz", - "integrity": "sha1-gob53efOzeeQX73ATiTzaPI/jaY=", - "dev": true, - "requires": { - "util-extend": "^1.0.1" - } - }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" - }, - "ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", - "dev": true, - "requires": { - "type": "^2.5.0" - }, - "dependencies": { - "type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - } - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-set": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", - "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", - "dev": true, - "requires": { - "array-back": "^5.0.0", - "glob": "^7.1.6" - }, - "dependencies": { - "array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true - } - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, - "requires": { - "array-back": "^3.0.1" - }, - "dependencies": { - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true - } - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fs-access": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", - "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", - "dev": true, - "requires": { - "null-check": "^1.0.0" - } - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, - "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-then-native": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", - "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gauge": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.0.tgz", - "integrity": "sha512-F8sU45yQpjQjxKkm1UOAhf0U/O0aFt//Fl7hsrNVto+patMHjs7dPI9mFOGUKbhrgKm0S3EjW3scMFuQmWSROw==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1", - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", - "dev": true, - "requires": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "ghreleases": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/ghreleases/-/ghreleases-3.0.2.tgz", - "integrity": "sha512-QiR9mIYvRG7hd8JuQYoxeBNOelVuTp2DpdiByRywbCDBSJufK9Vq7VuhD8B+5uviMxZx2AEkCzye61Us9gYgnw==", - "dev": true, - "requires": { - "after": "~0.8.1", - "ghrepos": "~2.1.0", - "ghutils": "~3.2.0", - "lodash.uniq": "^4.5.0", - "simple-mime": "~0.1.0", - "url-template": "~2.0.6" - } - }, - "ghrepos": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ghrepos/-/ghrepos-2.1.0.tgz", - "integrity": "sha512-6GM0ohSDTAv7xD6GsKfxJiV/CajoofRyUwu0E8l29d1o6lFAUxmmyMP/FH33afA20ZrXzxxcTtN6TsYvudMoAg==", - "dev": true, - "requires": { - "ghutils": "~3.2.0" - } - }, - "ghutils": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/ghutils/-/ghutils-3.2.6.tgz", - "integrity": "sha512-WpYHgLQkqU7Cv147wKUEThyj6qKHCdnAG2CL9RRsRQImVdLGdVqblJ3JUnj3ToQwgm1ALPS+FXgR0448AgGPUg==", - "dev": true, - "requires": { - "jsonist": "~2.1.0", - "xtend": "~4.0.1" - } - }, - "git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", - "dev": true, - "requires": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "dependencies": { - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "requires": { - "readable-stream": "3" - } - } - } - }, - "git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", - "dev": true, - "requires": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - } - }, - "git-semver-tags": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", - "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", - "dev": true, - "requires": { - "meow": "^8.0.0", - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", - "dev": true, - "requires": { - "ini": "^1.3.2" - } - }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "hyperquest": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/hyperquest/-/hyperquest-2.1.3.tgz", - "integrity": "sha512-fUuDOrB47PqNK/BAMOS13v41UoaqIxqSLHX6CAbOD7OfT+/GCWO1/vPLfTNutOeXrv1ikuaZ3yux+33Z9vh+rw==", - "dev": true, - "requires": { - "buffer-from": "^0.1.1", - "duplexer2": "~0.0.2", - "through2": "~0.6.3" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "irregular-plurals": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.4.0.tgz", - "integrity": "sha512-YXxECO/W6N9aMBVKMKKZ8TXESgq7EFrp3emCGGUcrYY1cgJIeZjoB75MTu8qi+NAKntS9NwPU8VdcQ3r6E6aWQ==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-iojs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-iojs/-/is-iojs-1.1.0.tgz", - "integrity": "sha1-TBEDO11dlNbqs3dd7cm+fQCDJfE=", - "dev": true - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", - "dev": true, - "requires": { - "text-extensions": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, - "requires": { - "xmlcreate": "^2.0.4" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "jsdoc": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.10.tgz", - "integrity": "sha512-IdQ8ppSo5LKZ9o3M+LKIIK8i00DIe5msDvG3G81Km+1dhy0XrOWD0Ji8H61ElgyEj/O9KRLokgKbAM9XX9CJAg==", - "dev": true, - "requires": { - "@babel/parser": "^7.9.4", - "@types/markdown-it": "^12.2.3", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.2", - "klaw": "^4.0.1", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.4.1", - "marked": "^4.0.10", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.13.2" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "jsdoc-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.1.1.tgz", - "integrity": "sha512-0pkuPCzVXiqsDAsVrNFXCkHzlyNepBIDVtwwehry4RJAnZmXtlAz7rh8F9FRz53u3NeynGbex+bpYWwi8lE66A==", - "dev": true, - "requires": { - "array-back": "^6.2.2", - "cache-point": "^2.0.0", - "collect-all": "^1.0.4", - "file-set": "^4.0.2", - "fs-then-native": "^2.0.0", - "jsdoc": "^3.6.10", - "object-to-spawn-args": "^2.0.1", - "temp-path": "^1.0.0", - "walk-back": "^5.1.0" - } - }, - "jsdoc-parse": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.1.0.tgz", - "integrity": "sha512-n/hDGQJa69IBun1yZAjqzV4gVR41+flZ3bIlm9fKvNe2Xjsd1/+zCo2+R9ls8LxtePgIWbpA1jU7xkB2lRdLLg==", - "dev": true, - "requires": { - "array-back": "^6.2.2", - "lodash.omit": "^4.5.0", - "lodash.pick": "^4.4.0", - "reduce-extract": "^1.0.0", - "sort-array": "^4.1.4", - "test-value": "^3.0.0" - } - }, - "jsdoc-to-markdown": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.1.tgz", - "integrity": "sha512-CI86d63xAVNO+ENumWwmJ034lYe5iGU5GwjtTA11EuphP9tpnoi4hrKgR/J8uME0D+o4KUpVfwX1fjZhc8dEtg==", - "dev": true, - "requires": { - "array-back": "^6.2.2", - "command-line-tool": "^0.8.0", - "config-master": "^3.1.0", - "dmd": "^6.1.0", - "jsdoc-api": "^7.1.1", - "jsdoc-parse": "^6.1.0", - "walk-back": "^5.1.0" - } - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/jsonist/-/jsonist-2.1.2.tgz", - "integrity": "sha512-8yqmWJAC2VaYoSKQAbsfgCpGY5o/1etWzx6ZxaZrC4iGaHrHUZEo+a2MyF8w+2uTavTlHdLWaZUoR19UfBstxQ==", - "dev": true, - "requires": { - "bl": "~3.0.0", - "hyperquest": "~2.1.3", - "json-stringify-safe": "~5.0.1", - "xtend": "~4.0.1" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "klaw": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.0.1.tgz", - "integrity": "sha512-pgsE40/SvC7st04AHiISNewaIMUbY5V/K8b21ekiPiFoYs/EYSdsGa+FJArB1d441uq4Q8zZyIxvAzkGNlBdRw==", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", - "dev": true - }, - "lodash.pad": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", - "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", - "dev": true - }, - "lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", - "dev": true - }, - "lodash.padstart": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", - "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", - "dev": true - }, - "lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "loupe": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", - "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", - "dev": true, - "requires": { - "get-func-name": "^2.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - } - } - }, - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true - }, - "markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, - "requires": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - } - }, - "markdown-it-anchor": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.4.1.tgz", - "integrity": "sha512-sLODeRetZ/61KkKLJElaU3NuU2z7MhXf12Ml1WJMSdwpngeofneCRF+JBbat8HiSqhniOMuTemXMrsI7hA6XyA==", - "dev": true, - "requires": {} - }, - "marked": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", - "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", - "dev": true - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "dev": true, - "optional": true - }, - "memory-stream": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-0.0.3.tgz", - "integrity": "sha1-6+jdHDuLw4wOeUHp3dWuvmtN6D8=", - "dev": true, - "requires": { - "readable-stream": "~1.0.26-2" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true - } - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, - "requires": { - "mime-db": "1.51.0" - } - }, - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - } - }, - "minipass": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", - "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, - "mkdirp2": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", - "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", - "dev": true - }, - "mocha": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", - "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "4.2.1", - "ms": "2.1.3", - "nanoid": "3.3.1", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "minimatch": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", - "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "dev": true - }, - "mongodb": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.9.0.tgz", - "integrity": "sha512-tJJEFJz7OQTQPZeVHZJIeSOjMRqc5eSyXTt86vSQENEErpkiG7279tM/GT5AVZ7TgXNh9HQxoa2ZkbrANz5GQw==", - "dev": true, - "requires": { - "bson": "^4.7.0", - "denque": "^2.1.0", - "mongodb-connection-string-url": "^2.5.3", - "saslprep": "^1.0.3", - "socks": "^2.7.0" - } - }, - "mongodb-connection-string-url": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.3.tgz", - "integrity": "sha512-f+/WsED+xF4B74l3k9V/XkTVj5/fxFH2o5ToKXd8Iyi5UhM+sO9u0Ape17Mvl/GkZaFtM0HQnzAG5OTmhKw+tQ==", - "dev": true, - "requires": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true - }, - "napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nise": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.1.tgz", - "integrity": "sha512-yr5kW2THW1AkxVmCnKEh4nbYkJdB3I7LUkiUgOvEkOp414mc2UMaHMA7pjq1nYowhdoJZGwEKGaQVbxfpWj10A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": ">=5", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node-abi": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.7.0.tgz", - "integrity": "sha512-3J+U4CvxVNEk9+lGdJkmYbN8cIN0HMTDT9R0ezX7pmp7aD6BaKsfAHwVn3IvVg6pYIRUuQ+gHW1eawrvywnSQQ==", - "requires": { - "semver": "^7.3.5" - } - }, - "node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" - }, - "node-gyp": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", - "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - } - }, - "node-ninja": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/node-ninja/-/node-ninja-1.0.2.tgz", - "integrity": "sha1-IKCeV7kuLfWRmT1L8JisPnJwYrY=", - "dev": true, - "requires": { - "fstream": "^1.0.0", - "glob": "3 || 4 || 5 || 6 || 7", - "graceful-fs": "^4.1.2", - "minimatch": "3", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2", - "osenv": "0", - "path-array": "^1.0.0", - "request": "2", - "rimraf": "2", - "semver": "2.x || 3.x || 4 || 5", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "gauge": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", - "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", - "dev": true, - "requires": { - "ansi": "^0.3.0", - "has-unicode": "^2.0.0", - "lodash.pad": "^4.1.0", - "lodash.padend": "^4.1.0", - "lodash.padstart": "^4.1.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "npmlog": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", - "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", - "dev": true, - "requires": { - "ansi": "~0.3.1", - "are-we-there-yet": "~1.1.2", - "gauge": "~1.2.5" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "noop-logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", - "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", - "dev": true - }, - "nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "requires": { - "abbrev": "^1.0.0" - } - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-path": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", - "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", - "dev": true, - "requires": { - "which": "^1.2.10" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "npm-which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", - "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", - "dev": true, - "requires": { - "commander": "^2.9.0", - "npm-path": "^2.0.2", - "which": "^1.2.10" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "npmlog": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.0.tgz", - "integrity": "sha512-03ppFRGlsyUaQFbGC2C8QWJN/C/K7PsfyD9aQdhVKAQIH4sQBc8WASqFBP7O+Ut4d2oo5LoeoboB3cGdBZSp6Q==", - "dev": true, - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.0", - "set-blocking": "^2.0.0" - } - }, - "null-check": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", - "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "nw-gyp": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/nw-gyp/-/nw-gyp-3.6.5.tgz", - "integrity": "sha512-vYrOIYJEKpq9CfaHuiqEjV1rBYgr6uaUrPhPRiznb91LujkAUqGhQ5QqDC1bLdd+zo9jf2H0Zkl2M5zQB7+CuQ==", - "dev": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "2", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-get": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", - "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", - "dev": true - }, - "object-to-spawn-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", - "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-array": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-array/-/path-array-1.0.1.tgz", - "integrity": "sha1-fi8PNfB6IBUSK4aLfqwOssT+wnE=", - "dev": true, - "requires": { - "array-index": "^1.0.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "plur": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", - "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", - "dev": true, - "requires": { - "irregular-plurals": "^3.2.0" - } - }, - "prebuild": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/prebuild/-/prebuild-11.0.3.tgz", - "integrity": "sha512-0synbTNdYD9nkVFtVl0nbslM6AefnKRcvyvtDwv6qswh4gYCbdWGmir4G7YPPDa3VmKCZADVBYnkqNI3qKJy5Q==", - "dev": true, - "requires": { - "cmake-js": "~5.2.0", - "detect-libc": "^2.0.0", - "each-series-async": "^1.0.1", - "execspawn": "^1.0.1", - "ghreleases": "^3.0.2", - "github-from-package": "0.0.0", - "glob": "^7.1.6", - "minimist": "^1.1.2", - "mkdirp": "^0.5.1", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.0.0", - "node-gyp": "^6.0.1", - "node-ninja": "^1.0.1", - "noop-logger": "^0.1.0", - "npm-which": "^3.0.1", - "npmlog": "^4.0.1", - "nw-gyp": "^3.6.3", - "rc": "^1.0.3", - "run-waterfall": "^1.1.6", - "tar-stream": "^2.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "node-gyp": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-6.1.0.tgz", - "integrity": "sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "mkdirp": "^0.5.1", - "nopt": "^4.0.1", - "npmlog": "^4.1.2", - "request": "^2.88.0", - "rimraf": "^2.6.3", - "semver": "^5.7.1", - "tar": "^4.4.12", - "which": "^1.3.1" - } - }, - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "dev": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "dev": true, - "requires": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - } - } - }, - "prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", - "requires": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - } - } - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - } - }, - "reduce-extract": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", - "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", - "dev": true, - "requires": { - "test-value": "^1.0.1" - }, - "dependencies": { - "array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "requires": { - "typical": "^2.6.0" - } - }, - "test-value": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", - "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", - "dev": true, - "requires": { - "array-back": "^1.0.2", - "typical": "^2.4.2" - } - } - } - }, - "reduce-flatten": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", - "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", - "dev": true - }, - "reduce-unique": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", - "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", - "dev": true - }, - "reduce-without": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", - "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", - "dev": true, - "requires": { - "test-value": "^2.0.0" - }, - "dependencies": { - "array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "requires": { - "typical": "^2.6.0" - } - }, - "test-value": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", - "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", - "dev": true, - "requires": { - "array-back": "^1.0.3", - "typical": "^2.6.0" - } - } - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rsvp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", - "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", - "dev": true - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "run-waterfall": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/run-waterfall/-/run-waterfall-1.1.7.tgz", - "integrity": "sha512-iFPgh7SatHXOG1ClcpdwHI63geV3Hc/iL6crGSyBlH2PY7Rm/za+zoKz6FfY/Qlw5K7JwSol8pseO8fN6CMhhQ==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "dev": true, - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" - }, - "simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "requires": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "simple-mime": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/simple-mime/-/simple-mime-0.1.0.tgz", - "integrity": "sha1-lfUXxPRm18/1YacfydqyWW6p7y4=", - "dev": true - }, - "sinon": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.1.tgz", - "integrity": "sha512-8yx2wIvkBjIq/MGY1D9h1LMraYW+z1X0mb648KZnKSdvLasvDu7maa0dFaNYdTDczFgbjNw2tOmWdTk9saVfwQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^9.0.0", - "@sinonjs/samsam": "^6.1.1", - "diff": "^5.0.0", - "nise": "^5.1.1", - "supports-color": "^7.2.0" - } - }, - "sinon-chai": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "dev": true, - "requires": {} - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" - }, - "socks": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", - "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "sort-array": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.4.tgz", - "integrity": "sha512-GVFN6Y1sHKrWaSYOJTk9093ZnrBMc9sP3nuhANU44S4xg3rE6W5Z5WyamuT8VpMBbssnetx5faKCua0LEmUnSw==", - "dev": true, - "requires": { - "array-back": "^5.0.0", - "typical": "^6.0.1" - }, - "dependencies": { - "array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true - }, - "typical": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", - "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", - "dev": true - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", - "integrity": "sha1-6lo5AKHByyUJagrozFwrSxDe09w=", - "dev": true, - "requires": { - "source-map": "0.1.32" - }, - "dependencies": { - "source-map": { - "version": "0.1.32", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", - "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "dev": true, - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "requires": { - "readable-stream": "^3.0.0" - } - }, - "splitargs": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/splitargs/-/splitargs-0.0.7.tgz", - "integrity": "sha1-/p965lc3GzOxDLgNoUPPgknPazs=", - "dev": true - }, - "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "standard-version": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", - "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "conventional-changelog": "3.1.24", - "conventional-changelog-config-spec": "2.1.0", - "conventional-changelog-conventionalcommits": "4.6.1", - "conventional-recommended-bump": "6.1.0", - "detect-indent": "^6.0.0", - "detect-newline": "^3.1.0", - "dotgitignore": "^2.1.0", - "figures": "^3.1.0", - "find-up": "^5.0.0", - "fs-access": "^1.0.1", - "git-semver-tags": "^4.0.0", - "semver": "^7.1.1", - "stringify-package": "^1.0.1", - "yargs": "^16.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "stream-connect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", - "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", - "dev": true, - "requires": { - "array-back": "^1.0.2" - }, - "dependencies": { - "array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "requires": { - "typical": "^2.6.0" - } - } - } - }, - "stream-via": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", - "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", - "dev": true - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "stringify-package": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", - "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "table-layout": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", - "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", - "dev": true, - "requires": { - "array-back": "^2.0.0", - "deep-extend": "~0.6.0", - "lodash.padend": "^4.6.1", - "typical": "^2.6.1", - "wordwrapjs": "^3.0.0" - }, - "dependencies": { - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - } - } - }, - "taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", - "dev": true - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - }, - "dependencies": { - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - } - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - } - } - }, - "temp-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", - "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", - "dev": true - }, - "test-value": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", - "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", - "dev": true, - "requires": { - "array-back": "^2.0.0", - "typical": "^2.6.1" - }, - "dependencies": { - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - } - } - }, - "text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "traceur": { - "version": "0.0.111", - "resolved": "https://registry.npmjs.org/traceur/-/traceur-0.0.111.tgz", - "integrity": "sha1-wE3nTRRpbDNzQn3k/Ajsr5E/w6E=", - "dev": true, - "requires": { - "commander": "2.9.x", - "glob": "5.0.x", - "rsvp": "^3.0.13", - "semver": "^4.3.3", - "source-map-support": "~0.2.8" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - } - } - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true - }, - "tsd": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.25.0.tgz", - "integrity": "sha512-liUlvKtsdr+70XEZP/kkF6U8+Q9URZi4Pw58ih7a9x3kjJblG8rdVgvG62xcvkgRva1q3yWX5qAxfYZuYiC5CA==", - "dev": true, - "requires": { - "@tsd/typescript": "~4.9.3", - "eslint-formatter-pretty": "^4.1.0", - "globby": "^11.0.1", - "meow": "^9.0.0", - "path-exists": "^4.0.0", - "read-pkg-up": "^7.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "uglify-js": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.0.tgz", - "integrity": "sha512-x+xdeDWq7FiORDvyIJ0q/waWd4PhjBNOm5dQUOq2AKC0IEjxOS66Ha9tctiVDGcRQuh69K7fgU5oRuTK4cysSg==", - "dev": true, - "optional": true - }, - "underscore": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.2.tgz", - "integrity": "sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g==", - "dev": true - }, - "unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "requires": { - "unique-slug": "^3.0.0" - } - }, - "unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unzipper": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.8.14.tgz", - "integrity": "sha512-8rFtE7EP5ssOwGpN2dt1Q4njl0N1hUXJ7sSPz0leU2hRdq6+pra57z4YPBlVqm40vcgv6ooKZEAx48fMTv9x4w==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "~1.0.10", - "listenercount": "~1.0.1", - "readable-stream": "~2.1.5", - "setimmediate": "~1.0.4" - }, - "dependencies": { - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "readable-stream": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", - "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", - "dev": true, - "requires": { - "buffer-shims": "^1.0.0", - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-join": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", - "integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g=", - "dev": true - }, - "url-template": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "util-extend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", - "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "walk-back": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", - "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", - "dev": true - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", - "dev": true - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wordwrapjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", - "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", - "dev": true, - "requires": { - "reduce-flatten": "^1.0.1", - "typical": "^2.6.1" - }, - "dependencies": { - "reduce-flatten": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", - "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", - "dev": true - } - } - }, - "workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - } - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/package.json b/ext/libmongocrypt/libmongocrypt/bindings/node/package.json deleted file mode 100644 index 02cac16..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/package.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "name": "mongodb-client-encryption", - "version": "2.8.0-alpha.1", - "description": "Official client encryption module for the MongoDB Node.js driver", - "main": "lib/index.js", - "types": "index.d.ts", - "files": [ - "README.md", - "CHANGELOG.md", - "lib", - "src", - "index.d.ts", - "binding.gyp" - ], - "directories": { - "lib": "lib" - }, - "scripts": { - "install": "prebuild-install --runtime napi --tag-prefix node-v || node-gyp rebuild", - "check:lint": "eslint lib test && tsd", - "docs": "jsdoc2md --template etc/README.hbs --plugin dmd-clear --files 'lib/**/*.js' > README.md", - "test": "mocha test", - "rebuild": "prebuild --compile", - "release": "standard-version --tag-prefix node-v --path bindings/node", - "prebuild": "prebuild --runtime napi --strip --verbose --tag-prefix node-v --all" - }, - "author": { - "name": "The MongoDB NodeJS Team", - "email": "dbx-node@mongodb.com" - }, - "bugs": { - "url": "https://jira.mongodb.org/projects/NODE/issues/" - }, - "license": "Apache-2.0", - "gypfile": true, - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^4.3.0", - "prebuild-install": "^7.1.1", - "socks": "^2.6.1" - }, - "devDependencies": { - "@types/sinon": "^10.0.13", - "@types/sinon-chai": "^3.2.9", - "chai": "^4.3.6", - "chai-subset": "^1.6.0", - "chalk": "^4.1.2", - "clang-format": "^1.6.0", - "dmd-clear": "^0.1.2", - "eslint": "^8.8.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-prettier": "^4.0.0", - "jsdoc-to-markdown": "^7.1.1", - "mocha": "^9.2.0", - "mongodb": "^4.9.0", - "node-gyp": "^9.3.1", - "prebuild": "^11.0.2", - "prettier": "^2.5.1", - "sinon": "^13.0.1", - "sinon-chai": "^3.7.0", - "standard-version": "^9.3.2", - "tar": "^6.1.11", - "tsd": "^0.25.0" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.186.0", - "gcp-metadata": "^5.2.0", - "mongodb": ">=3.4.0" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "gcp-metadata": { - "optional": true - } - }, - "engines": { - "node": ">=12.9.0" - }, - "binary": { - "napi_versions": [ - 4 - ] - }, - "repository": { - "type": "git", - "url": "https://github.com/mongodb/libmongocrypt", - "directory": "bindings/node" - }, - "tsd": { - "directory": "test/types", - "compilerOptions": { - "strict": true, - "target": "esnext", - "module": "commonjs", - "moduleResolution": "node" - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/src/mongocrypt.cc b/ext/libmongocrypt/libmongocrypt/bindings/node/src/mongocrypt.cc deleted file mode 100644 index 9b1724c..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/src/mongocrypt.cc +++ /dev/null @@ -1,956 +0,0 @@ -#include "mongocrypt.h" -#include - -#ifdef _MSC_VER -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - -namespace node_mongocrypt { - -using namespace Napi; - -// anonymous namepace for helpers -namespace { -struct InstanceData { - Reference MongoCryptContextCtor; - Reference MongoCryptKMSRequestCtor; -}; - -struct MongoCryptStatusDeleter { - void operator()(mongocrypt_status_t* status) { - mongocrypt_status_destroy(status); - } -}; - -Object ExtractStatus(Env env, mongocrypt_status_t* status) { - Object result = Object::New(env); - result["type"] = Number::New(env, mongocrypt_status_type(status)); - result["code"] = Number::New(env, mongocrypt_status_code(status)); - const char* message = mongocrypt_status_message(status, nullptr); - if (message != nullptr) { - result["message"] = String::New(env, message); - } - - return result; -} - -std::unique_ptr -BufferToBinary(Uint8Array node_buffer) { - uint8_t* buffer = node_buffer.Data(); - size_t buffer_len = node_buffer.ByteLength(); - return std::unique_ptr( - mongocrypt_binary_new_from_data(buffer, buffer_len)); -} - -Uint8Array BufferFromBinary(Env env, mongocrypt_binary_t* binary) { - const uint8_t* data = mongocrypt_binary_data(binary); - size_t len = mongocrypt_binary_len(binary); - return Buffer::Copy(env, data, len); -} - -Uint8Array BufferWithLengthOf(Env env, mongocrypt_binary_t* binary) { - size_t len = mongocrypt_binary_len(binary); - return Buffer::New(env, len); -} - -void CopyBufferData(mongocrypt_binary_t* out, Uint8Array buffer, size_t count) { - assert(count <= mongocrypt_binary_len(out)); - assert(count <= buffer.ByteLength()); - memcpy(mongocrypt_binary_data(out), buffer.Data(), count); -} - -void CopyBufferData(mongocrypt_binary_t* out, Uint8Array buffer) { - CopyBufferData(out, buffer, mongocrypt_binary_len(out)); -} - -std::string errorStringFromStatus(mongocrypt_t* crypt) { - std::unique_ptr status(mongocrypt_status_new()); - mongocrypt_status(crypt, status.get()); - const char* errorMessage = mongocrypt_status_message(status.get(), nullptr); - if (!errorMessage) { - return "Operation failed"; - } - - return errorMessage; -} - -std::string errorStringFromStatus(mongocrypt_ctx_t* context) { - std::unique_ptr status(mongocrypt_status_new()); - mongocrypt_ctx_status(context, status.get()); - const char* errorMessage = mongocrypt_status_message(status.get(), nullptr); - if (!errorMessage) { - return "Operation failed"; - } - - return errorMessage; -} - -template -E strToEnumValue( - Env env, - const std::string& str, - const char* option_name, - const std::initializer_list>& values) { - for (const auto& candidate : values) { - if (candidate.first == str) { - return candidate.second; - } - } - throw Error::New(env, - std::string("invalid enum value: '") + str + "' for " + option_name); -} - -} // anonymous namespace - -Function MongoCrypt::Init(Napi::Env env) { - return - DefineClass(env, - "MongoCrypt", - { - InstanceMethod("makeEncryptionContext", &MongoCrypt::MakeEncryptionContext), - InstanceMethod("makeExplicitEncryptionContext", &MongoCrypt::MakeExplicitEncryptionContext), - InstanceMethod("makeDecryptionContext", &MongoCrypt::MakeDecryptionContext), - InstanceMethod("makeExplicitDecryptionContext", &MongoCrypt::MakeExplicitDecryptionContext), - InstanceMethod("makeDataKeyContext", &MongoCrypt::MakeDataKeyContext), - InstanceMethod("makeRewrapManyDataKeyContext", &MongoCrypt::MakeRewrapManyDataKeyContext), - InstanceAccessor("status", &MongoCrypt::Status, nullptr), - InstanceAccessor("cryptSharedLibVersionInfo", &MongoCrypt::CryptSharedLibVersionInfo, nullptr), - StaticValue("libmongocryptVersion", String::New(env, mongocrypt_version(nullptr))) - }); -} - -void MongoCrypt::logHandler(mongocrypt_log_level_t level, - const char* message, - uint32_t message_len, - void* ctx) { - MongoCrypt* mongoCrypt = static_cast(ctx); - if (!mongoCrypt) { - fprintf(stderr, "Log handler called without `MongoCrypt` instance\n"); - return; - } - - Napi::Env env = mongoCrypt->Env(); - HandleScope scope(env); - Function logger = mongoCrypt->GetCallback("logger"); - - if (logger.IsEmpty()) { - fprintf(stderr, "No logger set, but log handler registered\n"); - return; - } - - try { - logger.Call(std::initializer_list - { Number::New(env, level), String::New(env, message, message_len) }); - } catch (const std::exception& ex) { - fprintf(stderr, "Uncaught exception in logger callback: %s\n", ex.what()); - } catch (...) { - fprintf(stderr, "Uncaught exception in logger callback\n"); - } -} - - -static void MaybeSetCryptoHookErrorStatus(Value result, mongocrypt_status_t *status) { - if (!result.IsObject()) { - return; - } - Object hookError = result.As(); - if (!hookError.Has("message")) { - return; - } - std::string errorMessage = hookError.Get("message").ToString(); - mongocrypt_status_set( - status, - MONGOCRYPT_STATUS_ERROR_CLIENT, - 1, - errorMessage.c_str(), - errorMessage.length() + 1 - ); -} - -static bool aes_256_generic_hook (MongoCrypt* mongoCrypt, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status, Function hook) { - Env env = mongoCrypt->Env(); - HandleScope scope(env); - - Uint8Array keyBuffer = BufferFromBinary(env, key); - Uint8Array ivBuffer = BufferFromBinary(env, iv); - Uint8Array inBuffer = BufferFromBinary(env, in); - Uint8Array outBuffer = BufferWithLengthOf(env, out); - - Value result; - try { - result = hook.Call(std::initializer_list - { keyBuffer, ivBuffer, inBuffer, outBuffer }); - } catch (...) { - return false; - } - - if (!result.IsNumber()) { - MaybeSetCryptoHookErrorStatus(result, status); - return false; - } - - *bytes_written = result.ToNumber().Uint32Value(); - CopyBufferData(out, outBuffer, *bytes_written); - return true; -} - -bool MongoCrypt::setupCryptoHooks() { - auto aes_256_cbc_encrypt = - [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status) -> bool { - MongoCrypt* mc = static_cast(ctx); - return aes_256_generic_hook(mc, key, iv, in, out, bytes_written, status, mc->GetCallback("aes256CbcEncryptHook")); - }; - - auto aes_256_cbc_decrypt = - [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status) -> bool { - MongoCrypt* mc = static_cast(ctx); - return aes_256_generic_hook(mc, key, iv, in, out, bytes_written, status, mc->GetCallback("aes256CbcDecryptHook")); - }; - - auto aes_256_ctr_encrypt = - [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status) -> bool { - MongoCrypt* mc = static_cast(ctx); - return aes_256_generic_hook(mc, key, iv, in, out, bytes_written, status, mc->GetCallback("aes256CtrEncryptHook")); - }; - - auto aes_256_ctr_decrypt = - [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *iv, mongocrypt_binary_t *in, mongocrypt_binary_t *out, uint32_t *bytes_written, mongocrypt_status_t *status) -> bool { - MongoCrypt* mc = static_cast(ctx); - return aes_256_generic_hook(mc, key, iv, in, out, bytes_written, status, mc->GetCallback("aes256CtrDecryptHook")); - }; - - auto random = - [](void *ctx, mongocrypt_binary_t *out, uint32_t count, mongocrypt_status_t *status) -> bool { - MongoCrypt* mongoCrypt = static_cast(ctx); - Napi::Env env = mongoCrypt->Env(); - HandleScope scope(env); - Function hook = mongoCrypt->GetCallback("randomHook"); - - Uint8Array outBuffer = BufferWithLengthOf(env, out); - Napi::Value result; - try { - result = hook.Call(std::initializer_list - { outBuffer, Number::New(env, count) }); - } catch (...) { - return false; - } - - if (!result.IsNumber()) { - MaybeSetCryptoHookErrorStatus(result, status); - return false; - } - - CopyBufferData(out, outBuffer); - return true; - }; - - auto hmac_sha_512 = - [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status) -> bool { - MongoCrypt* mongoCrypt = static_cast(ctx); - Napi::Env env = mongoCrypt->Env(); - HandleScope scope(env); - Function hook = mongoCrypt->GetCallback("hmacSha512Hook"); - - Uint8Array keyBuffer = BufferFromBinary(env, key); - Uint8Array inputBuffer = BufferFromBinary(env, in); - Uint8Array outputBuffer = BufferWithLengthOf(env, out); - - Napi::Value result; - try { - result = hook.Call(std::initializer_list - { keyBuffer, inputBuffer, outputBuffer }); - } catch (...) { - return false; - } - - if (!result.IsNumber()) { - MaybeSetCryptoHookErrorStatus(result, status); - return false; - } - - CopyBufferData(out, outputBuffer); - return true; - }; - - auto hmac_sha_256 = - [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status) -> bool { - MongoCrypt* mongoCrypt = static_cast(ctx); - Napi::Env env = mongoCrypt->Env(); - HandleScope scope(env); - Function hook = mongoCrypt->GetCallback("hmacSha256Hook"); - - Uint8Array keyBuffer = BufferFromBinary(env, key); - Uint8Array inputBuffer = BufferFromBinary(env, in); - Uint8Array outputBuffer = BufferWithLengthOf(env, out); - - Napi::Value result; - try { - result = hook.Call(std::initializer_list - { keyBuffer, inputBuffer, outputBuffer }); - } catch (...) { - return false; - } - - if (!result.IsNumber()) { - MaybeSetCryptoHookErrorStatus(result, status); - return false; - } - - CopyBufferData(out, outputBuffer); - return true; - }; - - auto sha_256 = - [](void *ctx, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status) -> bool { - MongoCrypt* mongoCrypt = static_cast(ctx); - Napi::Env env = mongoCrypt->Env(); - HandleScope scope(env); - Function hook = mongoCrypt->GetCallback("sha256Hook"); - - Uint8Array inputBuffer = BufferFromBinary(env, in); - Uint8Array outputBuffer = BufferWithLengthOf(env, out); - - Napi::Value result; - try { - result = hook.Call(std::initializer_list - { inputBuffer, outputBuffer }); - } catch (...) { - return false; - } - - if (!result.IsNumber()) { - MaybeSetCryptoHookErrorStatus(result, status); - return false; - } - - CopyBufferData(out, outputBuffer); - return true; - }; - - auto sign_rsa_sha256 = - [](void *ctx, mongocrypt_binary_t *key, mongocrypt_binary_t *in, mongocrypt_binary_t *out, mongocrypt_status_t *status) -> bool { - MongoCrypt* mongoCrypt = static_cast(ctx); - Napi::Env env = mongoCrypt->Env(); - HandleScope scope(env); - Function hook = mongoCrypt->GetCallback("signRsaSha256Hook"); - - Uint8Array keyBuffer = BufferFromBinary(env, key); - Uint8Array inputBuffer = BufferFromBinary(env, in); - Uint8Array outputBuffer = BufferWithLengthOf(env, out); - - Napi::Value result; - try { - result = hook.Call(std::initializer_list - { keyBuffer, inputBuffer, outputBuffer }); - } catch (...) { - return false; - } - - if (!result.IsNumber()) { - MaybeSetCryptoHookErrorStatus(result, status); - return false; - } - - CopyBufferData(out, outputBuffer); - return true; - }; - - if (!mongocrypt_setopt_crypto_hooks(_mongo_crypt.get(), - aes_256_cbc_encrypt, - aes_256_cbc_decrypt, - random, - hmac_sha_512, - hmac_sha_256, - sha_256, - this)) { - return false; - } - - // Added after `mongocrypt_setopt_crypto_hooks`, they should be treated as the same during configuration - if (!mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(_mongo_crypt.get(), sign_rsa_sha256, this)) { - return false; - } - - if (!mongocrypt_setopt_aes_256_ctr(_mongo_crypt.get(), aes_256_ctr_encrypt, aes_256_ctr_decrypt, this)) { - return false; - } - - return true; -} - -MongoCrypt::MongoCrypt(const CallbackInfo& info) - : ObjectWrap(info), _mongo_crypt(mongocrypt_new()) { - if (info.Length() < 1 || !info[0].IsObject()) { - throw TypeError::New(Env(), "First parameter must be an object"); - } - - Object options = info[0].ToObject(); - - if (options.Has("kmsProviders")) { - Napi::Value kmsProvidersOptions = options["kmsProviders"]; - - if (!kmsProvidersOptions.IsBuffer()) { - throw TypeError::New(Env(), "Option `kmsProviders` must be a Buffer"); - } - - std::unique_ptr kmsProvidersBinary( - BufferToBinary(kmsProvidersOptions.As())); - if (!mongocrypt_setopt_kms_providers(_mongo_crypt.get(), kmsProvidersBinary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); - } - } - - if (options.Has("schemaMap")) { - Napi::Value schemaMapBuffer = options["schemaMap"]; - - if (!schemaMapBuffer.IsBuffer()) { - throw TypeError::New(Env(), "Option `schemaMap` must be a Buffer"); - } - - std::unique_ptr schemaMapBinary( - BufferToBinary(schemaMapBuffer.As())); - if (!mongocrypt_setopt_schema_map(_mongo_crypt.get(), schemaMapBinary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); - } - } - - if (options.Has("encryptedFieldsMap")) { - Napi::Value encryptedFieldsMapBuffer = options["encryptedFieldsMap"]; - - if (!encryptedFieldsMapBuffer.IsBuffer()) { - throw TypeError::New(Env(), "Option `encryptedFieldsMap` must be a Buffer"); - } - - std::unique_ptr encryptedFieldsMapBinary( - BufferToBinary(encryptedFieldsMapBuffer.As())); - if (!mongocrypt_setopt_encrypted_field_config_map(_mongo_crypt.get(), encryptedFieldsMapBinary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); - } - } - - if (options.Has("logger")) { - SetCallback("logger", options["logger"]); - if (!mongocrypt_setopt_log_handler( - _mongo_crypt.get(), MongoCrypt::logHandler, this)) { - throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); - } - } - - if (options.Has("cryptoCallbacks")) { - Object cryptoCallbacks = options.Get("cryptoCallbacks").ToObject(); - - SetCallback("aes256CbcEncryptHook", cryptoCallbacks["aes256CbcEncryptHook"]); - SetCallback("aes256CbcDecryptHook", cryptoCallbacks["aes256CbcDecryptHook"]); - SetCallback("aes256CtrEncryptHook", cryptoCallbacks["aes256CtrEncryptHook"]); - SetCallback("aes256CtrDecryptHook", cryptoCallbacks["aes256CtrDecryptHook"]); - SetCallback("randomHook", cryptoCallbacks["randomHook"]); - SetCallback("hmacSha512Hook", cryptoCallbacks["hmacSha512Hook"]); - SetCallback("hmacSha256Hook", cryptoCallbacks["hmacSha256Hook"]); - SetCallback("sha256Hook", cryptoCallbacks["sha256Hook"]); - SetCallback("signRsaSha256Hook", cryptoCallbacks["signRsaSha256Hook"]); - - if (!setupCryptoHooks()) { - throw Error::New(Env(), "unable to configure crypto hooks"); - } - } - - if (options.Has("cryptSharedLibSearchPaths")) { - Napi::Value search_paths_v = options["cryptSharedLibSearchPaths"]; - if (!search_paths_v.IsArray()) { - throw TypeError::New(Env(), "Option `cryptSharedLibSearchPaths` must be an array"); - } - Array search_paths = search_paths_v.As(); - for (uint32_t i = 0; i < search_paths.Length(); i++) { - mongocrypt_setopt_append_crypt_shared_lib_search_path( - _mongo_crypt.get(), - search_paths.Get(i).ToString().Utf8Value().c_str()); - } - } - - if (options.Has("cryptSharedLibPath")) { - mongocrypt_setopt_set_crypt_shared_lib_path_override( - _mongo_crypt.get(), - options.Get("cryptSharedLibPath").ToString().Utf8Value().c_str()); - } - - if (options.Get("bypassQueryAnalysis").ToBoolean()) { - mongocrypt_setopt_bypass_query_analysis(_mongo_crypt.get()); - } - - mongocrypt_setopt_use_need_kms_credentials_state(_mongo_crypt.get()); - - // Initialize after all options are set. - if (!mongocrypt_init(_mongo_crypt.get())) { - throw TypeError::New(Env(), errorStringFromStatus(_mongo_crypt.get())); - } -} - -Value MongoCrypt::CryptSharedLibVersionInfo(const CallbackInfo& info) { - uint64_t version_numeric = mongocrypt_crypt_shared_lib_version(_mongo_crypt.get()); - const char* version_string = mongocrypt_crypt_shared_lib_version_string(_mongo_crypt.get(), nullptr); - if (version_string == nullptr) { - return Env().Null(); - } - - Object ret = Object::New(Env()); - ret["version"] = BigInt::New(Env(), version_numeric); - ret["versionStr"] = String::New(Env(), version_string); - return ret; -} - -Value MongoCrypt::Status(const CallbackInfo& info) { - std::unique_ptr status(mongocrypt_status_new()); - mongocrypt_status(_mongo_crypt.get(), status.get()); - return ExtractStatus(Env(), status.get()); -} - -Value MongoCrypt::MakeEncryptionContext(const CallbackInfo& info) { - std::string ns = info[0].ToString(); - std::unique_ptr context( - mongocrypt_ctx_new(_mongo_crypt.get())); - - Napi::Value commandBuffer = info[1]; - if (!commandBuffer.IsBuffer()) { - throw TypeError::New(Env(), "Parameter `command` must be a Buffer"); - } - - std::unique_ptr binaryCommand(BufferToBinary(commandBuffer.As())); - if (!mongocrypt_ctx_encrypt_init( - context.get(), ns.c_str(), ns.size(), binaryCommand.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - - return MongoCryptContext::NewInstance(Env(), std::move(context)); -} - -Value MongoCrypt::MakeExplicitEncryptionContext(const CallbackInfo& info) { - std::unique_ptr context( - mongocrypt_ctx_new(_mongo_crypt.get())); - - Napi::Value valueBuffer = info[0]; - if (!valueBuffer.IsBuffer()) { - throw TypeError::New(Env(), "Parameter `value` must be a Buffer"); - } - - Object options = info.Length() > 1 ? info[1].ToObject() : Object::New(info.Env()); - - if (options.Has("keyId")) { - Napi::Value keyId = options["keyId"]; - - if (!keyId.IsBuffer()) { - throw TypeError::New(Env(), "`keyId` must be a Buffer"); - } - - std::unique_ptr binary(BufferToBinary(keyId.As())); - if (!mongocrypt_ctx_setopt_key_id(context.get(), binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - } - - if (options.Has("keyAltName")) { - Napi::Value keyAltName = options["keyAltName"]; - - if (!keyAltName.IsBuffer()) { - throw TypeError::New(Env(), "`keyAltName` must be a Buffer"); - } - - std::unique_ptr binary( - BufferToBinary(keyAltName.As())); - if (!mongocrypt_ctx_setopt_key_alt_name(context.get(), binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - } - - if (options.Has("algorithm")) { - std::string algorithm = options.Get("algorithm").ToString(); - if (!mongocrypt_ctx_setopt_algorithm( - context.get(), algorithm.c_str(), algorithm.size())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - - if (strcasecmp(algorithm.c_str(), "rangepreview") == 0) { - if (!options.Has("rangeOptions")) { - throw TypeError::New(Env(), "`rangeOptions` must be provided if `algorithm` is set to RangePreview"); - } - - Napi::Value rangeOptions = options["rangeOptions"]; - - if (!rangeOptions.IsBuffer()) { - throw TypeError::New(Env(), "`rangeOptions` must be a Buffer"); - } - - std::unique_ptr binary(BufferToBinary(rangeOptions.As())); - if (!mongocrypt_ctx_setopt_algorithm_range(context.get(), binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - } - } - - if (options.Has("contentionFactor")) { - Napi::Value contention_factor_value = options["contentionFactor"]; - int64_t contention_factor = contention_factor_value.IsBigInt() ? - contention_factor_value.As().Int64Value(nullptr) : - contention_factor_value.ToNumber().Int64Value(); - if (!mongocrypt_ctx_setopt_contention_factor(context.get(), contention_factor)) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - } - - if (options.Has("queryType")) { - std::string query_type_str = options.Get("queryType").ToString(); - if (!mongocrypt_ctx_setopt_query_type(context.get(), query_type_str.data(), -1)) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - } - - std::unique_ptr binaryValue(BufferToBinary(valueBuffer.As())); - - const bool isExpressionMode = options.Get("expressionMode").ToBoolean(); - - const bool status = isExpressionMode - ? mongocrypt_ctx_explicit_encrypt_expression_init(context.get(), binaryValue.get()) - : mongocrypt_ctx_explicit_encrypt_init(context.get(), binaryValue.get()); - - if (!status) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - - return MongoCryptContext::NewInstance(Env(), std::move(context)); -} - -Value MongoCrypt::MakeDecryptionContext(const CallbackInfo& info) { - if (!info[0].IsBuffer()) { - throw TypeError::New(Env(), "First parameter must be a Buffer"); - } - - std::unique_ptr binary( - BufferToBinary(info[0].As())); - std::unique_ptr context( - mongocrypt_ctx_new(_mongo_crypt.get())); - - if (!mongocrypt_ctx_decrypt_init(context.get(), binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - - return MongoCryptContext::NewInstance(Env(), std::move(context)); -} - -Value MongoCrypt::MakeExplicitDecryptionContext(const CallbackInfo& info) { - if (!info[0].IsBuffer()) { - throw TypeError::New(Env(), "First parameter must be a Buffer"); - } - - std::unique_ptr binary( - BufferToBinary(info[0].As())); - std::unique_ptr context( - mongocrypt_ctx_new(_mongo_crypt.get())); - - if (!mongocrypt_ctx_explicit_decrypt_init(context.get(), binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - - return MongoCryptContext::NewInstance(Env(), std::move(context)); -} - -Value MongoCrypt::MakeDataKeyContext(const CallbackInfo& info) { - Napi::Value optionsBuffer = info[0]; - if (!optionsBuffer.IsBuffer()) { - throw TypeError::New(Env(), "Parameter `options` must be a Buffer"); - } - - std::unique_ptr context( - mongocrypt_ctx_new(_mongo_crypt.get())); - std::unique_ptr binary( - BufferToBinary(optionsBuffer.As())); - - if (!mongocrypt_ctx_setopt_key_encryption_key(context.get(), binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - - Object options = info[1].ToObject(); - if (options.Has("keyAltNames")) { - Napi::Value keyAltNames = options["keyAltNames"]; - - if (keyAltNames.IsArray()) { - Array keyAltNamesArray = keyAltNames.As(); - uint32_t keyAltNamesLength = keyAltNamesArray.Length(); - for (uint32_t i = 0; i < keyAltNamesLength; i += 1) { - if (keyAltNamesArray.Has(i)) { - Napi::Value keyAltName = keyAltNamesArray[i]; - if (!keyAltName.IsBuffer()) { - // We should never get here - throw TypeError::New(Env(), "Serialized keyAltName must be a Buffer"); - } - - std::unique_ptr binary( - BufferToBinary(keyAltName.As())); - if (!mongocrypt_ctx_setopt_key_alt_name(context.get(), binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - } - } - } - } - - if (options.Has("keyMaterial")) { - Napi::Value keyMaterial = options["keyMaterial"]; - - if (!keyMaterial.IsUndefined()) { - if (!keyMaterial.IsBuffer()) { - // We should never get here - throw TypeError::New(Env(), "Serialized keyMaterial must be a Buffer"); - } - - std::unique_ptr binary( - BufferToBinary(keyMaterial.As())); - if (!mongocrypt_ctx_setopt_key_material(context.get(), binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - } - } - - if (!mongocrypt_ctx_datakey_init(context.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - - return MongoCryptContext::NewInstance(Env(), std::move(context)); -} - -Value MongoCrypt::MakeRewrapManyDataKeyContext(const CallbackInfo& info) { - Napi::Value filter_buffer = info[0]; - if (!filter_buffer.IsBuffer()) { - throw TypeError::New(Env(), "Parameter `options` must be a Buffer"); - } - - std::unique_ptr context( - mongocrypt_ctx_new(_mongo_crypt.get())); - - Napi::Value key_encryption_key = info[1]; - if (key_encryption_key.IsBuffer()) { - std::unique_ptr key_binary( - BufferToBinary(key_encryption_key.As())); - if (!mongocrypt_ctx_setopt_key_encryption_key(context.get(), key_binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - } - - std::unique_ptr filter_binary( - BufferToBinary(filter_buffer.As())); - if (!mongocrypt_ctx_rewrap_many_datakey_init(context.get(), filter_binary.get())) { - throw TypeError::New(Env(), errorStringFromStatus(context.get())); - } - - return MongoCryptContext::NewInstance(Env(), std::move(context)); -} - -// Store callbacks as nested properties on the MongoCrypt binding object -// itself, and use these helpers to do so. Storing them as JS engine -// References is a big memory leak footgun. -Function MongoCrypt::GetCallback(const char* name) { - Napi::Value storage = Value().Get("__callbackStorage"); - if (!storage.IsObject()) { - throw Error::New(Env(), "Cannot get callbacks becauses none were registered"); - } - Napi::Value entry = storage.As().Get(name); - if (!entry.IsFunction()) { - throw Error::New(Env(), std::string("Trying to look up unknown callback ") + name); - } - return entry.As(); -} - -void MongoCrypt::SetCallback(const char* name, Napi::Value fn) { - if (!fn.IsFunction()) { - throw Error::New(Env(), std::string("Storing non-function as callback ") + name); - } - - Napi::Value storage = Value().Get("__callbackStorage"); - if (!storage.IsObject()) { - storage = Object::New(Env()); - Value().Set("__callbackStorage", storage); - } - storage.As().Set(name, fn); -} - -Function MongoCryptContext::Init(Napi::Env env) { - return - DefineClass(env, - "MongoCryptContext", - { - InstanceMethod("nextMongoOperation", &MongoCryptContext::NextMongoOperation), - InstanceMethod("addMongoOperationResponse", &MongoCryptContext::AddMongoOperationResponse), - InstanceMethod("finishMongoOperation", &MongoCryptContext::FinishMongoOperation), - InstanceMethod("nextKMSRequest", &MongoCryptContext::NextKMSRequest), - InstanceMethod("provideKMSProviders", &MongoCryptContext::ProvideKMSProviders), - InstanceMethod("finishKMSRequests", &MongoCryptContext::FinishKMSRequests), - InstanceMethod("finalize", &MongoCryptContext::FinalizeContext), - InstanceAccessor("status", &MongoCryptContext::Status, nullptr), - InstanceAccessor("state", &MongoCryptContext::State, nullptr) - }); -} - -Object MongoCryptContext::NewInstance(Napi::Env env, std::unique_ptr context) { - InstanceData* instance_data = env.GetInstanceData(); - Object obj = instance_data->MongoCryptContextCtor.Value().New({}); - MongoCryptContext* instance = MongoCryptContext::Unwrap(obj); - instance->_context = std::move(context); - return obj; -} - -MongoCryptContext::MongoCryptContext(const CallbackInfo& info) - : ObjectWrap(info) {} - -Value MongoCryptContext::Status(const CallbackInfo& info) { - std::unique_ptr status(mongocrypt_status_new()); - mongocrypt_ctx_status(_context.get(), status.get()); - return ExtractStatus(Env(), status.get()); -} - -Value MongoCryptContext::State(const CallbackInfo& info) { - return Number::New(Env(), mongocrypt_ctx_state(_context.get())); -} - -Value MongoCryptContext::NextMongoOperation(const CallbackInfo& info) { - std::unique_ptr op_bson(mongocrypt_binary_new()); - mongocrypt_ctx_mongo_op(_context.get(), op_bson.get()); - return BufferFromBinary(Env(), op_bson.get()); -} - -void MongoCryptContext::AddMongoOperationResponse(const CallbackInfo& info) { - if (info.Length() != 1 || !info[0].IsObject()) { - throw TypeError::New(Env(), "Missing required parameter `buffer`"); - } - - if (!info[0].IsBuffer()) { - throw TypeError::New(Env(), "First parameter must be a Buffer"); - } - - std::unique_ptr reply_bson( - BufferToBinary(info[0].As())); - mongocrypt_ctx_mongo_feed(_context.get(), reply_bson.get()); - // return value -} - -void MongoCryptContext::FinishMongoOperation(const CallbackInfo& info) { - mongocrypt_ctx_mongo_done(_context.get()); -} - -void MongoCryptContext::ProvideKMSProviders(const CallbackInfo& info) { - if (info.Length() != 1 || !info[0].IsObject()) { - throw TypeError::New(Env(), "Missing required parameter `buffer`"); - } - - if (!info[0].IsBuffer()) { - throw TypeError::New(Env(), "First parameter must be a Buffer"); - } - - std::unique_ptr kms_bson( - BufferToBinary(info[0].As())); - mongocrypt_ctx_provide_kms_providers(_context.get(), kms_bson.get()); -} - -Value MongoCryptContext::NextKMSRequest(const CallbackInfo& info) { - mongocrypt_kms_ctx_t* kms_context = mongocrypt_ctx_next_kms_ctx(_context.get()); - if (kms_context == nullptr) { - return Env().Null(); - } else { - Object result = MongoCryptKMSRequest::NewInstance(Env(), kms_context); - // The lifetime of the `kms_context` pointer is not specified - // anywhere, so it seems reasonable to assume that it is at - // least the lifetime of this context object. - // Use a symbol to enforce that lifetime dependency. - result.Set("__kmsRequestContext", Value()); - return result; - } -} - -void MongoCryptContext::FinishKMSRequests(const CallbackInfo& info) { - mongocrypt_ctx_kms_done(_context.get()); -} - -Value MongoCryptContext::FinalizeContext(const CallbackInfo& info) { - std::unique_ptr output(mongocrypt_binary_new()); - mongocrypt_ctx_finalize(_context.get(), output.get()); - return BufferFromBinary(Env(), output.get()); -} - -Function MongoCryptKMSRequest::Init(Napi::Env env) { - return - DefineClass(env, - "MongoCryptKMSRequest", - { - InstanceMethod("addResponse", &MongoCryptKMSRequest::AddResponse), - InstanceAccessor("status", &MongoCryptKMSRequest::Status, nullptr), - InstanceAccessor("bytesNeeded", &MongoCryptKMSRequest::BytesNeeded, nullptr), - InstanceAccessor("kmsProvider", &MongoCryptKMSRequest::KMSProvider, nullptr), - InstanceAccessor("endpoint", &MongoCryptKMSRequest::Endpoint, nullptr), - InstanceAccessor("message", &MongoCryptKMSRequest::Message, nullptr) - }); -} - -Object MongoCryptKMSRequest::NewInstance(Napi::Env env, mongocrypt_kms_ctx_t* kms_context) { - InstanceData* instance_data = env.GetInstanceData(); - Object obj = instance_data->MongoCryptKMSRequestCtor.Value().New({}); - MongoCryptKMSRequest* instance = MongoCryptKMSRequest::Unwrap(obj); - instance->_kms_context = kms_context; - return obj; -} - -MongoCryptKMSRequest::MongoCryptKMSRequest(const CallbackInfo& info) - : ObjectWrap(info), _kms_context(nullptr) {} - -Value MongoCryptKMSRequest::Status(const CallbackInfo& info) { - std::unique_ptr status(mongocrypt_status_new()); - mongocrypt_kms_ctx_status(_kms_context, status.get()); - return ExtractStatus(Env(), status.get()); -} - -Value MongoCryptKMSRequest::BytesNeeded(const CallbackInfo& info) { - return Number::New(Env(), mongocrypt_kms_ctx_bytes_needed(_kms_context)); -} - -Value MongoCryptKMSRequest::KMSProvider(const CallbackInfo& info) { - return String::New(Env(), mongocrypt_kms_ctx_get_kms_provider(_kms_context, nullptr)); -} - -Value MongoCryptKMSRequest::Message(const CallbackInfo& info) { - std::unique_ptr message(mongocrypt_binary_new()); - mongocrypt_kms_ctx_message(_kms_context, message.get()); - return BufferFromBinary(Env(), message.get()); -} - -Value MongoCryptKMSRequest::Endpoint(const CallbackInfo& info) { - std::unique_ptr message(mongocrypt_binary_new()); - - const char* endpoint; - mongocrypt_kms_ctx_endpoint(_kms_context, &endpoint); - return String::New(Env(), endpoint); -} - -void MongoCryptKMSRequest::AddResponse(const CallbackInfo& info) { - if (!info[0].IsBuffer()) { - throw TypeError::New(Env(), "First parameter must be of type Buffer"); - } - - std::unique_ptr reply_bytes( - BufferToBinary(info[0].As())); - mongocrypt_kms_ctx_feed(_kms_context, reply_bytes.get()); -} - -static Object Init(Env env, Object exports) { - Function MongoCryptCtor = MongoCrypt::Init(env); - Function MongoCryptContextCtor = MongoCryptContext::Init(env); - Function MongoCryptKMSRequestCtor = MongoCryptKMSRequest::Init(env); - exports["MongoCrypt"] = MongoCryptCtor; - exports["MongoCryptContextCtor"] = MongoCryptContextCtor; - exports["MongoCryptKMSRequestCtor"] = MongoCryptKMSRequestCtor; - env.SetInstanceData(new InstanceData { - Reference::New(MongoCryptContextCtor, 1), - Reference::New(MongoCryptKMSRequestCtor, 1) - }); - return exports; -} - -NODE_API_MODULE(mongocrypt, Init) - -} // namespace node_mongocrypt diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/src/mongocrypt.h b/ext/libmongocrypt/libmongocrypt/bindings/node/src/mongocrypt.h deleted file mode 100644 index b960e50..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/src/mongocrypt.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef NODE_MONGOCRYPT_H -#define NODE_MONGOCRYPT_H - -// We generally only target N-API version 4, but the instance data -// feature is only available in N-API version 6. However, it is -// available in all Node.js versions that have N-API version 4 -// as an experimental feature (that has not been changed since then). -#define NAPI_VERSION 6 -#define NAPI_EXPERIMENTAL - -#include -#include - -extern "C" { -#include -} - -namespace node_mongocrypt { - -struct MongoCryptBinaryDeleter { - void operator()(mongocrypt_binary_t* binary) { - mongocrypt_binary_destroy(binary); - } -}; - -struct MongoCryptDeleter { - void operator()(mongocrypt_t* mongo_crypt) { - mongocrypt_destroy(mongo_crypt); - } -}; - -struct MongoCryptContextDeleter { - void operator()(mongocrypt_ctx_t* context) { - mongocrypt_ctx_destroy(context); - } -}; - -class MongoCrypt : public Napi::ObjectWrap { - public: - static Napi::Function Init(Napi::Env env); - - private: - Napi::Value MakeEncryptionContext(const Napi::CallbackInfo& info); - Napi::Value MakeExplicitEncryptionContext(const Napi::CallbackInfo& info); - Napi::Value MakeDecryptionContext(const Napi::CallbackInfo& info); - Napi::Value MakeExplicitDecryptionContext(const Napi::CallbackInfo& info); - Napi::Value MakeDataKeyContext(const Napi::CallbackInfo& info); - Napi::Value MakeRewrapManyDataKeyContext(const Napi::CallbackInfo& info); - - Napi::Value Status(const Napi::CallbackInfo& info); - Napi::Value CryptSharedLibVersionInfo(const Napi::CallbackInfo& info); - - private: - friend class Napi::ObjectWrap; - Napi::Function GetCallback(const char* name); - void SetCallback(const char* name, Napi::Value fn); - - explicit MongoCrypt(const Napi::CallbackInfo& info); - bool setupCryptoHooks(); - - static void logHandler(mongocrypt_log_level_t level, - const char* message, - uint32_t message_len, - void* ctx); - - std::unique_ptr _mongo_crypt; -}; - -class MongoCryptContext : public Napi::ObjectWrap { - public: - static Napi::Function Init(Napi::Env env); - static Napi::Object NewInstance(Napi::Env env, std::unique_ptr context); - - private: - Napi::Value NextMongoOperation(const Napi::CallbackInfo& info); - void AddMongoOperationResponse(const Napi::CallbackInfo& info); - void FinishMongoOperation(const Napi::CallbackInfo& info); - Napi::Value NextKMSRequest(const Napi::CallbackInfo& info); - void ProvideKMSProviders(const Napi::CallbackInfo& info); - void FinishKMSRequests(const Napi::CallbackInfo& info); - Napi::Value FinalizeContext(const Napi::CallbackInfo& info); - - Napi::Value Status(const Napi::CallbackInfo& info); - Napi::Value State(const Napi::CallbackInfo& info); - - private: - friend class Napi::ObjectWrap; - explicit MongoCryptContext(const Napi::CallbackInfo& info); - std::unique_ptr _context; -}; - -class MongoCryptKMSRequest : public Napi::ObjectWrap { - public: - static Napi::Function Init(Napi::Env env); - static Napi::Object NewInstance(Napi::Env env, mongocrypt_kms_ctx_t* kms_context); - - private: - void AddResponse(const Napi::CallbackInfo& info); - - Napi::Value Status(const Napi::CallbackInfo& info); - Napi::Value Message(const Napi::CallbackInfo& info); - Napi::Value BytesNeeded(const Napi::CallbackInfo& info); - Napi::Value KMSProvider(const Napi::CallbackInfo& info); - Napi::Value Endpoint(const Napi::CallbackInfo& info); - - private: - friend class Napi::ObjectWrap; - explicit MongoCryptKMSRequest(const Napi::CallbackInfo& info); - mongocrypt_kms_ctx_t* _kms_context; -}; - -} // namespace node_mongocrypt - -#endif // NODE_MONGOCRYPT_H diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/autoEncrypter.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/autoEncrypter.test.js deleted file mode 100644 index dbff311..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/autoEncrypter.test.js +++ /dev/null @@ -1,950 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const sinon = require('sinon'); -const mongodb = require('mongodb'); -const BSON = mongodb.BSON; -const EJSON = BSON.EJSON; -const requirements = require('./requirements.helper'); -const MongoNetworkTimeoutError = mongodb.MongoNetworkTimeoutError || mongodb.MongoTimeoutError; -const MongoError = mongodb.MongoError; -const stateMachine = require('../lib/stateMachine')({ mongodb }); -const StateMachine = stateMachine.StateMachine; -const MongocryptdManager = require('../lib/mongocryptdManager').MongocryptdManager; - -const { expect } = require('chai'); - -const sharedLibrarySuffix = - process.platform === 'win32' ? 'dll' : process.platform === 'darwin' ? 'dylib' : 'so'; -let sharedLibraryStub = path.resolve( - __dirname, - '..', - '..', - '..', - `mongo_crypt_v1.${sharedLibrarySuffix}` -); -if (!fs.existsSync(sharedLibraryStub)) { - sharedLibraryStub = path.resolve( - __dirname, - '..', - 'deps', - 'tmp', - 'libmongocrypt-build', - ...(process.platform === 'win32' ? ['RelWithDebInfo'] : []), - `mongo_crypt_v1.${sharedLibrarySuffix}` - ); -} - -function readExtendedJsonToBuffer(path) { - const ejson = EJSON.parse(fs.readFileSync(path, 'utf8')); - return BSON.serialize(ejson); -} - -function readHttpResponse(path) { - let data = fs.readFileSync(path, 'utf8'); - data = data.split('\n').join('\r\n'); - return Buffer.from(data, 'utf8'); -} - -const TEST_COMMAND = JSON.parse(fs.readFileSync(`${__dirname}/data/cmd.json`)); -const MOCK_COLLINFO_RESPONSE = readExtendedJsonToBuffer(`${__dirname}/data/collection-info.json`); -const MOCK_MONGOCRYPTD_RESPONSE = readExtendedJsonToBuffer( - `${__dirname}/data/mongocryptd-reply.json` -); -const MOCK_KEYDOCUMENT_RESPONSE = readExtendedJsonToBuffer(`${__dirname}/data/key-document.json`); -const MOCK_KMS_DECRYPT_REPLY = readHttpResponse(`${__dirname}/data/kms-decrypt-reply.txt`); - -class MockClient { - constructor() { - this.topology = { - bson: BSON - }; - } -} - -const originalAccessKeyId = process.env.AWS_ACCESS_KEY_ID; -const originalSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; - -const AutoEncrypter = require('../lib/autoEncrypter')({ mongodb, stateMachine }).AutoEncrypter; -describe('AutoEncrypter', function () { - this.timeout(12000); - let ENABLE_LOG_TEST = false; - let sandbox = sinon.createSandbox(); - beforeEach(() => { - sandbox.restore(); - sandbox.stub(StateMachine.prototype, 'kmsRequest').callsFake(request => { - request.addResponse(MOCK_KMS_DECRYPT_REPLY); - return Promise.resolve(); - }); - - sandbox - .stub(StateMachine.prototype, 'fetchCollectionInfo') - .callsFake((client, ns, filter, callback) => { - callback(null, MOCK_COLLINFO_RESPONSE); - }); - - sandbox - .stub(StateMachine.prototype, 'markCommand') - .callsFake((client, ns, command, callback) => { - if (ENABLE_LOG_TEST) { - const response = BSON.deserialize(MOCK_MONGOCRYPTD_RESPONSE); - response.schemaRequiresEncryption = false; - - ENABLE_LOG_TEST = false; // disable test after run - callback(null, BSON.serialize(response)); - return; - } - - callback(null, MOCK_MONGOCRYPTD_RESPONSE); - }); - - sandbox.stub(StateMachine.prototype, 'fetchKeys').callsFake((client, ns, filter, callback) => { - // mock data is already serialized, our action deals with the result of a cursor - const deserializedKey = BSON.deserialize(MOCK_KEYDOCUMENT_RESPONSE); - callback(null, [deserializedKey]); - }); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('#constructor', function () { - context('when mongodb exports BSON (driver >= 4.9.0)', function () { - context('when a bson option is provided', function () { - const bson = Object.assign({}, BSON); - const encrypter = new AutoEncrypter( - {}, - { - bson: bson, - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - } - ); - - it('uses the bson option', function () { - expect(encrypter._bson).to.equal(bson); - }); - }); - - context('when a bson option is not provided', function () { - const encrypter = new AutoEncrypter( - {}, - { - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - } - ); - - it('uses the mongodb exported BSON', function () { - expect(encrypter._bson).to.equal(BSON); - }); - }); - - it('never uses bson from the topology', function () { - expect(() => { - new AutoEncrypter( - {}, - { - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - } - ); - }).not.to.throw(); - }); - }); - - context('when mongodb does not export BSON (driver < 4.9.0)', function () { - context('when a bson option is provided', function () { - const bson = Object.assign({}, BSON); - const encrypter = new AutoEncrypter( - {}, - { - bson: bson, - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - } - ); - - it('uses the bson option', function () { - expect(encrypter._bson).to.equal(bson); - }); - }); - - context('when a bson option is not provided', function () { - const mongoNoBson = { ...mongodb, BSON: undefined }; - const AutoEncrypterNoBson = require('../lib/autoEncrypter')({ - mongodb: mongoNoBson, - stateMachine - }).AutoEncrypter; - - context('when the client has a topology', function () { - const client = new MockClient(); - const encrypter = new AutoEncrypterNoBson(client, { - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - }); - - it('uses the bson on the topology', function () { - expect(encrypter._bson).to.equal(client.topology.bson); - }); - }); - - context('when the client does not have a topology', function () { - it('raises an error', function () { - expect(() => { - new AutoEncrypterNoBson({}, {}); - }).to.throw(/bson/); - }); - }); - }); - }); - - context('when using mongocryptd', function () { - const client = new MockClient(); - const autoEncrypterOptions = { - mongocryptdBypassSpawn: true, - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }; - const autoEncrypter = new AutoEncrypter(client, autoEncrypterOptions); - - it('instantiates a mongo client on the auto encrypter', function () { - expect(autoEncrypter) - .to.have.property('_mongocryptdClient') - .to.be.instanceOf(mongodb.MongoClient); - }); - - it('sets the 3x legacy client options on the mongo client', function () { - expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); - const options = autoEncrypter._mongocryptdClient.s.options; - expect(options).to.have.property('useUnifiedTopology', true); - expect(options).to.have.property('useNewUrlParser', true); - }); - - it('sets serverSelectionTimeoutMS to 10000ms', function () { - expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); - const options = autoEncrypter._mongocryptdClient.s.options; - expect(options).to.have.property('serverSelectionTimeoutMS', 10000); - }); - - context('when mongocryptdURI is not specified', () => { - it('sets the ip address family to ipv4', function () { - expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); - const options = autoEncrypter._mongocryptdClient.s.options; - expect(options).to.have.property('family', 4); - }); - }); - - context('when mongocryptdURI is specified', () => { - it('does not set the ip address family to ipv4', function () { - const autoEncrypter = new AutoEncrypter(client, { - ...autoEncrypterOptions, - extraOptions: { mongocryptdURI: MongocryptdManager.DEFAULT_MONGOCRYPTD_URI } - }); - - expect(autoEncrypter).to.have.nested.property('_mongocryptdClient.s.options'); - const options = autoEncrypter._mongocryptdClient.s.options; - expect(options).not.to.have.property('family', 4); - }); - }); - }); - }); - - it('should support `bypassAutoEncryption`', function (done) { - const client = new MockClient(); - const autoEncrypter = new AutoEncrypter(client, { - bypassAutoEncryption: true, - mongocryptdBypassSpawn: true, - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }); - - autoEncrypter.encrypt('test.test', { test: 'command' }, (err, encrypted) => { - expect(err).to.not.exist; - expect(encrypted).to.eql({ test: 'command' }); - done(); - }); - }); - - describe('state machine', function () { - it('should decrypt mock data', function (done) { - const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); - const client = new MockClient(); - const mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }); - mc.decrypt(input, (err, decrypted) => { - if (err) return done(err); - expect(decrypted).to.eql({ filter: { find: 'test', ssn: '457-55-5462' } }); - expect(decrypted).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); - expect(decrypted.filter).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); - done(); - }); - }); - - it('should decrypt mock data and mark decrypted items if enabled for testing', function (done) { - const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); - const nestedInput = readExtendedJsonToBuffer( - `${__dirname}/data/encrypted-document-nested.json` - ); - const client = new MockClient(); - const mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }); - mc[Symbol.for('@@mdb.decorateDecryptionResult')] = true; - mc.decrypt(input, (err, decrypted) => { - if (err) return done(err); - expect(decrypted).to.eql({ filter: { find: 'test', ssn: '457-55-5462' } }); - expect(decrypted).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); - expect(decrypted.filter[Symbol.for('@@mdb.decryptedKeys')]).to.eql(['ssn']); - - // The same, but with an object containing different data types as the input - mc.decrypt({ a: [null, 1, { c: new BSON.Binary('foo', 1) }] }, (err, decrypted) => { - if (err) return done(err); - expect(decrypted).to.eql({ a: [null, 1, { c: new BSON.Binary('foo', 1) }] }); - expect(decrypted).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); - - // The same, but with nested data inside the decrypted input - mc.decrypt(nestedInput, (err, decrypted) => { - if (err) return done(err); - expect(decrypted).to.eql({ nested: { x: { y: 1234 } } }); - expect(decrypted[Symbol.for('@@mdb.decryptedKeys')]).to.eql(['nested']); - expect(decrypted.nested).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); - expect(decrypted.nested.x).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); - expect(decrypted.nested.x.y).to.not.have.property(Symbol.for('@@mdb.decryptedKeys')); - done(); - }); - }); - }); - }); - - it('should decrypt mock data with per-context KMS credentials', function (done) { - const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); - const client = new MockClient(); - const mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: {} - }, - async onKmsProviderRefresh() { - return { aws: { accessKeyId: 'example', secretAccessKey: 'example' } }; - } - }); - mc.decrypt(input, (err, decrypted) => { - if (err) return done(err); - expect(decrypted).to.eql({ filter: { find: 'test', ssn: '457-55-5462' } }); - done(); - }); - }); - - context('when no refresh function is provided', function () { - const accessKey = 'example'; - const secretKey = 'example'; - - before(function () { - if (!requirements.credentialProvidersInstalled.aws) { - this.currentTest.skipReason = 'Cannot refresh credentials without sdk provider'; - this.currentTest.skip(); - return; - } - // After the entire suite runs, set the env back for the rest of the test run. - process.env.AWS_ACCESS_KEY_ID = accessKey; - process.env.AWS_SECRET_ACCESS_KEY = secretKey; - }); - - after(function () { - // After the entire suite runs, set the env back for the rest of the test run. - process.env.AWS_ACCESS_KEY_ID = originalAccessKeyId; - process.env.AWS_SECRET_ACCESS_KEY = originalSecretAccessKey; - }); - - it('should decrypt mock data with KMS credentials from the environment', function (done) { - const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); - const client = new MockClient(); - const mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: {} - } - }); - mc.decrypt(input, (err, decrypted) => { - if (err) return done(err); - expect(decrypted).to.eql({ filter: { find: 'test', ssn: '457-55-5462' } }); - done(); - }); - }); - }); - - context('when no refresh function is provided and no optional sdk', function () { - const accessKey = 'example'; - const secretKey = 'example'; - - before(function () { - if (requirements.credentialProvidersInstalled.aws) { - this.currentTest.skipReason = 'With optional sdk installed credentials would be loaded.'; - this.currentTest.skip(); - return; - } - // After the entire suite runs, set the env back for the rest of the test run. - process.env.AWS_ACCESS_KEY_ID = accessKey; - process.env.AWS_SECRET_ACCESS_KEY = secretKey; - }); - - after(function () { - // After the entire suite runs, set the env back for the rest of the test run. - process.env.AWS_ACCESS_KEY_ID = originalAccessKeyId; - process.env.AWS_SECRET_ACCESS_KEY = originalSecretAccessKey; - }); - - it('errors without the optional sdk credential provider', function (done) { - const input = readExtendedJsonToBuffer(`${__dirname}/data/encrypted-document.json`); - const client = new MockClient(); - const mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: {} - } - }); - mc.decrypt(input, err => { - expect(err.message).to.equal( - 'client not configured with KMS provider necessary to decrypt' - ); - done(); - }); - }); - }); - - it('should encrypt mock data', function (done) { - const client = new MockClient(); - const mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }); - - mc.encrypt('test.test', TEST_COMMAND, (err, encrypted) => { - if (err) return done(err); - const expected = EJSON.parse( - JSON.stringify({ - find: 'test', - filter: { - ssn: { - $binary: { - base64: - 'AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=', - subType: '6' - } - } - } - }) - ); - - expect(encrypted).to.containSubset(expected); - done(); - }); - }); - - it('should encrypt mock data with per-context KMS credentials', function (done) { - const client = new MockClient(); - const mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: {} - }, - async onKmsProviderRefresh() { - return { aws: { accessKeyId: 'example', secretAccessKey: 'example' } }; - } - }); - - mc.encrypt('test.test', TEST_COMMAND, (err, encrypted) => { - if (err) return done(err); - const expected = EJSON.parse( - JSON.stringify({ - find: 'test', - filter: { - ssn: { - $binary: { - base64: - 'AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=', - subType: '6' - } - } - } - }) - ); - - expect(encrypted).to.containSubset(expected); - done(); - }); - }); - - // TODO(NODE-4089): Enable test once https://github.com/mongodb/libmongocrypt/pull/263 is done - it.skip('should encrypt mock data when using the crypt_shared library', function (done) { - const client = new MockClient(); - const mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: {} - }, - async onKmsProviderRefresh() { - return { aws: { accessKeyId: 'example', secretAccessKey: 'example' } }; - }, - extraOptions: { - cryptSharedLibPath: sharedLibraryStub - } - }); - - expect(mc).to.not.have.property('_mongocryptdManager'); - expect(mc).to.not.have.property('_mongocryptdClient'); - - mc.encrypt('test.test', TEST_COMMAND, (err, encrypted) => { - if (err) return done(err); - const expected = EJSON.parse( - JSON.stringify({ - find: 'test', - filter: { - ssn: { - $binary: { - base64: - 'AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=', - subType: '6' - } - } - } - }) - ); - - expect(encrypted).to.containSubset(expected); - done(); - }); - }); - }); - - describe('logging', function () { - it('should allow registration of a log handler', function (done) { - ENABLE_LOG_TEST = true; - - let loggerCalled = false; - const logger = (level, message) => { - if (loggerCalled) return; - - loggerCalled = true; - expect(level).to.be.oneOf([2, 3]); - expect(message).to.not.be.empty; - }; - - const client = new MockClient(); - const mc = new AutoEncrypter(client, { - logger, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }); - - mc.encrypt('test.test', TEST_COMMAND, (err, encrypted) => { - if (err) return done(err); - const expected = EJSON.parse( - JSON.stringify({ - find: 'test', - filter: { - ssn: '457-55-5462' - } - }) - ); - - expect(encrypted).to.containSubset(expected); - done(); - }); - }); - }); - - describe('autoSpawn', function () { - beforeEach(function () { - if (requirements.SKIP_LIVE_TESTS) { - this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; - this.currentTest.skip(); - return; - } - }); - afterEach(function (done) { - if (this.mc) { - this.mc.teardown(false, err => { - this.mc = undefined; - done(err); - }); - } else { - done(); - } - }); - - it('should autoSpawn a mongocryptd on init by default', function (done) { - const client = new MockClient(); - this.mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }); - - expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); - - const localMcdm = this.mc._mongocryptdManager; - sandbox.spy(localMcdm, 'spawn'); - - this.mc.init(err => { - if (err) return done(err); - expect(localMcdm.spawn).to.have.been.calledOnce; - done(); - }); - }); - - it('should not attempt to kick off mongocryptd on a normal error', function (done) { - let called = false; - StateMachine.prototype.markCommand.callsFake((client, ns, filter, callback) => { - if (!called) { - called = true; - callback(new Error('msg')); - return; - } - - callback(null, MOCK_MONGOCRYPTD_RESPONSE); - }); - - const client = new MockClient(); - this.mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }); - expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); - - const localMcdm = this.mc._mongocryptdManager; - this.mc.init(err => { - if (err) return done(err); - - sandbox.spy(localMcdm, 'spawn'); - - this.mc.encrypt('test.test', TEST_COMMAND, err => { - expect(localMcdm.spawn).to.not.have.been.called; - expect(err).to.be.an.instanceOf(Error); - done(); - }); - }); - }); - - it('should restore the mongocryptd and retry once if a MongoNetworkTimeoutError is experienced', function (done) { - let called = false; - StateMachine.prototype.markCommand.callsFake((client, ns, filter, callback) => { - if (!called) { - called = true; - callback(new MongoNetworkTimeoutError('msg')); - return; - } - - callback(null, MOCK_MONGOCRYPTD_RESPONSE); - }); - - const client = new MockClient(); - this.mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }); - expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); - - const localMcdm = this.mc._mongocryptdManager; - this.mc.init(err => { - if (err) return done(err); - - sandbox.spy(localMcdm, 'spawn'); - - this.mc.encrypt('test.test', TEST_COMMAND, err => { - expect(localMcdm.spawn).to.have.been.calledOnce; - expect(err).to.not.exist; - done(); - }); - }); - }); - - it('should propagate error if MongoNetworkTimeoutError is experienced twice in a row', function (done) { - let counter = 2; - StateMachine.prototype.markCommand.callsFake((client, ns, filter, callback) => { - if (counter) { - counter -= 1; - callback(new MongoNetworkTimeoutError('msg')); - return; - } - - callback(null, MOCK_MONGOCRYPTD_RESPONSE); - }); - - const client = new MockClient(); - this.mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - } - }); - expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); - - const localMcdm = this.mc._mongocryptdManager; - this.mc.init(err => { - if (err) return done(err); - - sandbox.spy(localMcdm, 'spawn'); - - this.mc.encrypt('test.test', TEST_COMMAND, err => { - expect(localMcdm.spawn).to.have.been.calledOnce; - expect(err).to.be.an.instanceof(MongoNetworkTimeoutError); - done(); - }); - }); - }); - - it('should return a useful message if mongocryptd fails to autospawn', function (done) { - const client = new MockClient(); - this.mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - }, - extraOptions: { - mongocryptdURI: 'mongodb://something.invalid:27020/' - } - }); - expect(this.mc).to.have.property('cryptSharedLibVersionInfo', null); - - sandbox.stub(MongocryptdManager.prototype, 'spawn').callsFake(callback => { - callback(); - }); - - this.mc.init(err => { - expect(err).to.exist; - expect(err).to.be.instanceOf(MongoError); - done(); - }); - }); - }); - - describe('noAutoSpawn', function () { - beforeEach('start MongocryptdManager', function (done) { - if (requirements.SKIP_LIVE_TESTS) { - this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; - this.skip(); - } - - this.mcdm = new MongocryptdManager({}); - this.mcdm.spawn(done); - }); - - afterEach(function (done) { - if (this.mc) { - this.mc.teardown(false, err => { - this.mc = undefined; - done(err); - }); - } else { - done(); - } - }); - - ['mongocryptdBypassSpawn', 'bypassAutoEncryption', 'bypassQueryAnalysis'].forEach(opt => { - const encryptionOptions = { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - }, - extraOptions: { - mongocryptdBypassSpawn: opt === 'mongocryptdBypassSpawn' - }, - bypassAutoEncryption: opt === 'bypassAutoEncryption', - bypassQueryAnalysis: opt === 'bypassQueryAnalysis' - }; - - it(`should not spawn mongocryptd on startup if ${opt} is true`, function (done) { - const client = new MockClient(); - this.mc = new AutoEncrypter(client, encryptionOptions); - - const localMcdm = this.mc._mongocryptdManager || { spawn: () => {} }; - sandbox.spy(localMcdm, 'spawn'); - - this.mc.init(err => { - expect(err).to.not.exist; - expect(localMcdm.spawn).to.have.a.callCount(0); - done(); - }); - }); - }); - - it('should not spawn a mongocryptd or retry on a server selection error if mongocryptdBypassSpawn: true', function (done) { - let called = false; - const timeoutError = new MongoNetworkTimeoutError('msg'); - StateMachine.prototype.markCommand.callsFake((client, ns, filter, callback) => { - if (!called) { - called = true; - callback(timeoutError); - return; - } - - callback(null, MOCK_MONGOCRYPTD_RESPONSE); - }); - - const client = new MockClient(); - this.mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - }, - extraOptions: { - mongocryptdBypassSpawn: true - } - }); - - const localMcdm = this.mc._mongocryptdManager; - sandbox.spy(localMcdm, 'spawn'); - - this.mc.init(err => { - expect(err).to.not.exist; - expect(localMcdm.spawn).to.not.have.been.called; - - this.mc.encrypt('test.test', TEST_COMMAND, (err, response) => { - expect(localMcdm.spawn).to.not.have.been.called; - expect(response).to.not.exist; - expect(err).to.equal(timeoutError); - done(); - }); - }); - }); - }); - - describe('crypt_shared library', function () { - it('should fail if no library can be found in the search path and cryptSharedLibRequired is set', function () { - // NB: This test has to be run before the tests/without having previously - // loaded a CSFLE shared library below to get the right error path. - const client = new MockClient(); - try { - new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - }, - extraOptions: { - cryptSharedLibSearchPaths: ['/nonexistent'], - cryptSharedLibRequired: true - } - }); - expect.fail('missed exception'); - } catch (err) { - expect(err.message).to.include( - '`cryptSharedLibRequired` set but no crypt_shared library loaded' - ); - } - }); - - it('should load a shared library by specifying its path', function (done) { - const client = new MockClient(); - this.mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - }, - extraOptions: { - cryptSharedLibPath: sharedLibraryStub - } - }); - - expect(this.mc).to.not.have.property('_mongocryptdManager'); - expect(this.mc).to.not.have.property('_mongocryptdClient'); - expect(this.mc).to.have.deep.property('cryptSharedLibVersionInfo', { - // eslint-disable-next-line no-undef - version: BigInt(0x000600020001000), - versionStr: 'stubbed-crypt_shared' - }); - - this.mc.teardown(true, done); - }); - - it('should load a shared library by specifying a search path', function (done) { - const client = new MockClient(); - this.mc = new AutoEncrypter(client, { - keyVaultNamespace: 'admin.datakeys', - logger: () => {}, - kmsProviders: { - aws: { accessKeyId: 'example', secretAccessKey: 'example' }, - local: { key: Buffer.alloc(96) } - }, - extraOptions: { - cryptSharedLibSearchPaths: [path.dirname(sharedLibraryStub)] - } - }); - - expect(this.mc).to.not.have.property('_mongocryptdManager'); - expect(this.mc).to.not.have.property('_mongocryptdClient'); - expect(this.mc).to.have.deep.property('cryptSharedLibVersionInfo', { - // eslint-disable-next-line no-undef - version: BigInt(0x000600020001000), - versionStr: 'stubbed-crypt_shared' - }); - - this.mc.teardown(true, done); - }); - }); - - it('should provide the libmongocrypt version', function () { - expect(AutoEncrypter.libmongocryptVersion).to.be.a('string'); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/buffer_pool.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/buffer_pool.test.js deleted file mode 100644 index 973e4f7..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/buffer_pool.test.js +++ /dev/null @@ -1,91 +0,0 @@ -'use strict'; - -const { BufferPool } = require('../lib/buffer_pool'); -const { expect } = require('chai'); - -describe('new BufferPool()', function () { - it('should report the correct length', function () { - const buffer = new BufferPool(); - buffer.append(Buffer.from([0, 1])); - buffer.append(Buffer.from([2, 3])); - buffer.append(Buffer.from([2, 3])); - expect(buffer).property('length').to.equal(6); - }); - - it('return an empty buffer if too many bytes requested', function () { - const buffer = new BufferPool(); - buffer.append(Buffer.from([0, 1, 2, 3])); - const data = buffer.read(6); - expect(data).to.have.length(0); - expect(buffer).property('length').to.equal(4); - }); - - context('peek', function () { - it('exact size', function () { - const buffer = new BufferPool(); - buffer.append(Buffer.from([0, 1])); - const data = buffer.peek(2); - expect(data).to.eql(Buffer.from([0, 1])); - expect(buffer).property('length').to.equal(2); - }); - - it('within first buffer', function () { - const buffer = new BufferPool(); - buffer.append(Buffer.from([0, 1, 2, 3])); - const data = buffer.peek(2); - expect(data).to.eql(Buffer.from([0, 1])); - expect(buffer).property('length').to.equal(4); - }); - - it('across multiple buffers', function () { - const buffer = new BufferPool(); - buffer.append(Buffer.from([0, 1])); - buffer.append(Buffer.from([2, 3])); - buffer.append(Buffer.from([4, 5])); - expect(buffer).property('length').to.equal(6); - const data = buffer.peek(5); - expect(data).to.eql(Buffer.from([0, 1, 2, 3, 4])); - expect(buffer).property('length').to.equal(6); - }); - }); - - context('read', function () { - it('should throw an error if a negative size is requested', function () { - const buffer = new BufferPool(); - expect(() => buffer.read(-1)).to.throw(/Argument "size" must be a non-negative number/); - }); - - it('should throw an error if a non-number size is requested', function () { - const buffer = new BufferPool(); - expect(() => buffer.read('256')).to.throw(/Argument "size" must be a non-negative number/); - }); - - it('exact size', function () { - const buffer = new BufferPool(); - buffer.append(Buffer.from([0, 1])); - const data = buffer.read(2); - expect(data).to.eql(Buffer.from([0, 1])); - expect(buffer).property('length').to.equal(0); - }); - - it('within first buffer', function () { - const buffer = new BufferPool(); - buffer.append(Buffer.from([0, 1, 2, 3])); - const data = buffer.read(2); - expect(data).to.eql(Buffer.from([0, 1])); - expect(buffer).property('length').to.equal(2); - }); - - it('across multiple buffers', function () { - const buffer = new BufferPool(); - buffer.append(Buffer.from([0, 1])); - buffer.append(Buffer.from([2, 3])); - buffer.append(Buffer.from([4, 5])); - expect(buffer).property('length').to.equal(6); - const data = buffer.read(5); - expect(data).to.eql(Buffer.from([0, 1, 2, 3, 4])); - expect(buffer).property('length').to.equal(1); - expect(buffer.read(1)).to.eql(Buffer.from([5])); - }); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/clientEncryption.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/clientEncryption.test.js deleted file mode 100644 index 837bb85..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/clientEncryption.test.js +++ /dev/null @@ -1,1093 +0,0 @@ -'use strict'; -const fs = require('fs'); -const { expect } = require('chai'); -const sinon = require('sinon'); -const mongodb = require('mongodb'); -const BSON = mongodb.BSON; -const MongoClient = mongodb.MongoClient; -const cryptoCallbacks = require('../lib/cryptoCallbacks'); -const stateMachine = require('../lib/stateMachine')({ mongodb }); -const StateMachine = stateMachine.StateMachine; -const { Binary, EJSON, deserialize } = BSON; -const { - MongoCryptCreateEncryptedCollectionError, - MongoCryptCreateDataKeyError -} = require('../lib/errors'); - -function readHttpResponse(path) { - let data = fs.readFileSync(path, 'utf8').toString(); - data = data.split('\n').join('\r\n'); - return Buffer.from(data, 'utf8'); -} - -const ClientEncryption = require('../lib/clientEncryption')({ - mongodb, - stateMachine -}).ClientEncryption; - -class MockClient { - constructor() { - this.topology = { - bson: BSON - }; - } - db(dbName) { - return { - async createCollection(name, options) { - return { namespace: `${dbName}.${name}`, options }; - } - }; - } -} - -const requirements = require('./requirements.helper'); - -describe('ClientEncryption', function () { - this.timeout(12000); - /** @type {MongoClient} */ - let client; - - function throwIfNotNsNotFoundError(err) { - if (!err.message.match(/ns not found/)) { - throw err; - } - } - - async function setup() { - client = new MongoClient(process.env.MONGODB_URI || 'mongodb://localhost:27017/test'); - await client.connect(); - try { - await client.db('client').collection('encryption').drop(); - } catch (err) { - throwIfNotNsNotFoundError(err); - } - } - - function teardown() { - if (requirements.SKIP_LIVE_TESTS) { - return Promise.resolve(); - } - - return client.close(); - } - - describe('#constructor', function () { - context('when mongodb exports BSON (driver >= 4.9.0)', function () { - context('when a bson option is provided', function () { - const bson = Object.assign({}, BSON); - const encrypter = new ClientEncryption( - {}, - { - bson: bson, - keyVaultNamespace: 'client.encryption', - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - } - ); - - it('uses the bson option', function () { - expect(encrypter._bson).to.equal(bson); - }); - }); - - context('when a bson option is not provided', function () { - const encrypter = new ClientEncryption( - {}, - { - keyVaultNamespace: 'client.encryption', - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - } - ); - - it('uses the mongodb exported BSON', function () { - expect(encrypter._bson).to.equal(BSON); - }); - }); - - it('never uses bson from the topology', function () { - expect(() => { - new ClientEncryption( - {}, - { - keyVaultNamespace: 'client.encryption', - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - } - ); - }).not.to.throw(); - }); - }); - - context('when mongodb does not export BSON (driver < 4.9.0)', function () { - context('when a bson option is provided', function () { - const bson = Object.assign({}, BSON); - const encrypter = new ClientEncryption( - {}, - { - bson: bson, - keyVaultNamespace: 'client.encryption', - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - } - ); - - it('uses the bson option', function () { - expect(encrypter._bson).to.equal(bson); - }); - }); - - context('when a bson option is not provided', function () { - const mongoNoBson = { ...mongodb, BSON: undefined }; - const ClientEncryptionNoBson = require('../lib/clientEncryption')({ - mongodb: mongoNoBson, - stateMachine - }).ClientEncryption; - - context('when the client has a topology', function () { - const client = new MockClient(); - const encrypter = new ClientEncryptionNoBson(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { - local: { key: Buffer.alloc(96) } - } - }); - - it('uses the bson on the topology', function () { - expect(encrypter._bson).to.equal(client.topology.bson); - }); - }); - - context('when the client does not have a topology', function () { - it('raises an error', function () { - expect(() => { - new ClientEncryptionNoBson({}, {}); - }).to.throw(/bson/); - }); - }); - }); - }); - }); - - describe('stubbed stateMachine', function () { - let sandbox = sinon.createSandbox(); - - after(() => sandbox.restore()); - before(() => { - // stubbed out for AWS unit testing below - const MOCK_KMS_ENCRYPT_REPLY = readHttpResponse(`${__dirname}/data/kms-encrypt-reply.txt`); - sandbox.stub(StateMachine.prototype, 'kmsRequest').callsFake(request => { - request.addResponse(MOCK_KMS_ENCRYPT_REPLY); - return Promise.resolve(); - }); - }); - - beforeEach(function () { - if (requirements.SKIP_LIVE_TESTS) { - this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; - this.test.skip(); - return; - } - - return setup(); - }); - - afterEach(function () { - return teardown(); - }); - - [ - { - name: 'local', - kmsProviders: { local: { key: Buffer.alloc(96) } } - }, - { - name: 'aws', - kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' } }, - options: { masterKey: { region: 'region', key: 'cmk' } } - } - ].forEach(providerTest => { - it(`should create a data key with the "${providerTest.name}" KMS provider`, async function () { - const providerName = providerTest.name; - const encryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: providerTest.kmsProviders - }); - - const dataKeyOptions = providerTest.options || {}; - - const dataKey = await encryption.createDataKey(providerName, dataKeyOptions); - expect(dataKey).property('_bsontype', 'Binary'); - - const doc = await client.db('client').collection('encryption').findOne({ _id: dataKey }); - expect(doc).to.have.property('masterKey'); - expect(doc.masterKey).property('provider', providerName); - }); - - it(`should create a data key with the "${providerTest.name}" KMS provider (fixed key material)`, async function () { - const providerName = providerTest.name; - const encryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: providerTest.kmsProviders - }); - - const dataKeyOptions = { - ...providerTest.options, - keyMaterial: new BSON.Binary(Buffer.alloc(96)) - }; - - const dataKey = await encryption.createDataKey(providerName, dataKeyOptions); - expect(dataKey).property('_bsontype', 'Binary'); - - const doc = await client.db('client').collection('encryption').findOne({ _id: dataKey }); - expect(doc).to.have.property('masterKey'); - expect(doc.masterKey).property('provider', providerName); - }); - }); - - it(`should create a data key with the local KMS provider (fixed key material, fixed key UUID)`, async function () { - // 'Custom Key Material Test' prose spec test: - const keyVaultColl = client.db('client').collection('encryption'); - const encryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { - local: { - key: 'A'.repeat(128) // the value here is not actually relevant - } - } - }); - - const dataKeyOptions = { - keyMaterial: new BSON.Binary( - Buffer.from( - 'xPTAjBRG5JiPm+d3fj6XLi2q5DMXUS/f1f+SMAlhhwkhDRL0kr8r9GDLIGTAGlvC+HVjSIgdL+RKwZCvpXSyxTICWSXTUYsWYPyu3IoHbuBZdmw2faM3WhcRIgbMReU5', - 'base64' - ) - ) - }; - const dataKey = await encryption.createDataKey('local', dataKeyOptions); - expect(dataKey._bsontype).to.equal('Binary'); - - // Remove and re-insert with a fixed UUID to guarantee consistent output - const doc = ( - await keyVaultColl.findOneAndDelete({ _id: dataKey }, { writeConcern: { w: 'majority' } }) - ).value; - doc._id = new BSON.Binary(Buffer.alloc(16), 4); - await keyVaultColl.insertOne(doc, { writeConcern: { w: 'majority' } }); - - const encrypted = await encryption.encrypt('test', { - keyId: doc._id, - algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' - }); - expect(encrypted._bsontype).to.equal('Binary'); - expect(encrypted.toString('base64')).to.equal( - 'AQAAAAAAAAAAAAAAAAAAAAACz0ZOLuuhEYi807ZXTdhbqhLaS2/t9wLifJnnNYwiw79d75QYIZ6M/aYC1h9nCzCjZ7pGUpAuNnkUhnIXM3PjrA==' - ); - }); - - it('should fail to create a data key if keyMaterial is wrong', function (done) { - const encryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: 'A'.repeat(128) } } - }); - - const dataKeyOptions = { - keyMaterial: new BSON.Binary(Buffer.alloc(97)) - }; - try { - encryption.createDataKey('local', dataKeyOptions); - expect.fail('missed exception'); - } catch (err) { - expect(err.message).to.equal('keyMaterial should have length 96, but has length 97'); - done(); - } - }); - - it('should explicitly encrypt and decrypt with the "local" KMS provider', function (done) { - const encryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: Buffer.alloc(96) } } - }); - - encryption.createDataKey('local', (err, dataKey) => { - expect(err).to.not.exist; - - const encryptOptions = { - keyId: dataKey, - algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' - }; - - encryption.encrypt('hello', encryptOptions, (err, encrypted) => { - expect(err).to.not.exist; - expect(encrypted._bsontype).to.equal('Binary'); - expect(encrypted.sub_type).to.equal(6); - - encryption.decrypt(encrypted, (err, decrypted) => { - expect(err).to.not.exist; - expect(decrypted).to.equal('hello'); - done(); - }); - }); - }); - }); - - it('should explicitly encrypt and decrypt with the "local" KMS provider (promise)', function () { - const encryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: Buffer.alloc(96) } } - }); - - return encryption - .createDataKey('local') - .then(dataKey => { - const encryptOptions = { - keyId: dataKey, - algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' - }; - - return encryption.encrypt('hello', encryptOptions); - }) - .then(encrypted => { - expect(encrypted._bsontype).to.equal('Binary'); - expect(encrypted.sub_type).to.equal(6); - - return encryption.decrypt(encrypted); - }) - .then(decrypted => { - expect(decrypted).to.equal('hello'); - }); - }); - - it('should explicitly encrypt and decrypt with a re-wrapped local key', function () { - // Create new ClientEncryption instances to make sure - // that we are actually using the rewrapped keys and not - // something that has been cached. - const newClientEncryption = () => - new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: 'A'.repeat(128) } } - }); - let encrypted; - - return newClientEncryption() - .createDataKey('local') - .then(dataKey => { - const encryptOptions = { - keyId: dataKey, - algorithm: 'Indexed', - contentionFactor: 0 - }; - - return newClientEncryption().encrypt('hello', encryptOptions); - }) - .then(_encrypted => { - encrypted = _encrypted; - expect(encrypted._bsontype).to.equal('Binary'); - expect(encrypted.sub_type).to.equal(6); - }) - .then(() => { - return newClientEncryption().rewrapManyDataKey({}); - }) - .then(rewrapManyDataKeyResult => { - expect(rewrapManyDataKeyResult.bulkWriteResult.result.nModified).to.equal(1); - return newClientEncryption().decrypt(encrypted); - }) - .then(decrypted => { - expect(decrypted).to.equal('hello'); - }); - }); - - it('should not perform updates if no keys match', function () { - const clientEncryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: 'A'.repeat(128) } } - }); - - return clientEncryption.rewrapManyDataKey({ _id: 12345 }).then(rewrapManyDataKeyResult => { - expect(rewrapManyDataKeyResult.bulkWriteResult).to.equal(undefined); - }); - }); - - it.skip('should explicitly encrypt and decrypt with a re-wrapped local key (explicit session/transaction)', function () { - const encryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: 'A'.repeat(128) } } - }); - let encrypted; - let rewrapManyDataKeyResult; - - return encryption - .createDataKey('local') - .then(dataKey => { - const encryptOptions = { - keyId: dataKey, - algorithm: 'Indexed', - contentionFactor: 0 - }; - - return encryption.encrypt('hello', encryptOptions); - }) - .then(_encrypted => { - encrypted = _encrypted; - }) - .then(() => { - // withSession does not forward the callback's return value, hence - // the slightly awkward 'rewrapManyDataKeyResult' passing here - return client.withSession(session => { - return session.withTransaction(() => { - expect(session.transaction.isStarting).to.equal(true); - expect(session.transaction.isActive).to.equal(true); - rewrapManyDataKeyResult = encryption.rewrapManyDataKey( - {}, - { provider: 'local', session } - ); - return rewrapManyDataKeyResult.then(() => { - // Verify that the 'session' argument was actually used - expect(session.transaction.isStarting).to.equal(false); - expect(session.transaction.isActive).to.equal(true); - }); - }); - }); - }) - .then(() => { - return rewrapManyDataKeyResult; - }) - .then(rewrapManyDataKeyResult => { - expect(rewrapManyDataKeyResult.bulkWriteResult.result.nModified).to.equal(1); - return encryption.decrypt(encrypted); - }) - .then(decrypted => { - expect(decrypted).to.equal('hello'); - }); - }).skipReason = 'TODO(DRIVERS-2389): add explicit session support to key management API'; - - // TODO(NODE-3371): resolve KMS JSON response does not include string 'Plaintext'. HTTP status=200 error - it.skip('should explicitly encrypt and decrypt with the "aws" KMS provider', function (done) { - const encryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { aws: { accessKeyId: 'example', secretAccessKey: 'example' } } - }); - - const dataKeyOptions = { - masterKey: { region: 'region', key: 'cmk' } - }; - - encryption.createDataKey('aws', dataKeyOptions, (err, dataKey) => { - expect(err).to.not.exist; - - const encryptOptions = { - keyId: dataKey, - algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' - }; - - encryption.encrypt('hello', encryptOptions, (err, encrypted) => { - expect(err).to.not.exist; - expect(encrypted).to.have.property('v'); - expect(encrypted.v._bsontype).to.equal('Binary'); - expect(encrypted.v.sub_type).to.equal(6); - - encryption.decrypt(encrypted, (err, decrypted) => { - expect(err).to.not.exist; - expect(decrypted).to.equal('hello'); - done(); - }); - }); - }); - }).skipReason = - "TODO(NODE-3371): resolve KMS JSON response does not include string 'Plaintext'. HTTP status=200 error"; - }); - - describe('ClientEncryptionKeyAltNames', function () { - const kmsProviders = requirements.awsKmsProviders; - const dataKeyOptions = requirements.awsDataKeyOptions; - beforeEach(function () { - if (requirements.SKIP_AWS_TESTS) { - this.currentTest.skipReason = `requirements.SKIP_AWS_TESTS=${requirements.SKIP_AWS_TESTS}`; - this.currentTest.skip(); - return; - } - - return setup().then(() => { - this.client = client; - this.collection = client.db('client').collection('encryption'); - this.encryption = new ClientEncryption(this.client, { - keyVaultNamespace: 'client.encryption', - kmsProviders - }); - }); - }); - - afterEach(function () { - return teardown().then(() => { - this.encryption = undefined; - this.collection = undefined; - this.client = undefined; - }); - }); - - function makeOptions(keyAltNames) { - expect(dataKeyOptions.masterKey).to.be.an('object'); - expect(dataKeyOptions.masterKey.key).to.be.a('string'); - expect(dataKeyOptions.masterKey.region).to.be.a('string'); - - return { - masterKey: { - key: dataKeyOptions.masterKey.key, - region: dataKeyOptions.masterKey.region - }, - keyAltNames - }; - } - - describe('errors', function () { - [42, 'hello', { keyAltNames: 'foobar' }, /foobar/].forEach(val => { - it(`should fail if typeof keyAltNames = ${typeof val}`, function () { - const options = makeOptions(val); - expect(() => this.encryption.createDataKey('aws', options, () => undefined)).to.throw( - TypeError - ); - }); - }); - - [undefined, null, 42, { keyAltNames: 'foobar' }, ['foobar'], /foobar/].forEach(val => { - it(`should fail if typeof keyAltNames[x] = ${typeof val}`, function () { - const options = makeOptions([val]); - expect(() => this.encryption.createDataKey('aws', options, () => undefined)).to.throw( - TypeError - ); - }); - }); - }); - - it('should create a key with keyAltNames', function () { - let dataKey; - const options = makeOptions(['foobar']); - return this.encryption - .createDataKey('aws', options) - .then(_dataKey => (dataKey = _dataKey)) - .then(() => this.collection.findOne({ keyAltNames: 'foobar' })) - .then(document => { - expect(document).to.be.an('object'); - expect(document).to.have.property('keyAltNames').that.includes.members(['foobar']); - expect(document).to.have.property('_id').that.deep.equals(dataKey); - }); - }); - - it('should create a key with multiple keyAltNames', function () { - let dataKey; - return this.encryption - .createDataKey('aws', makeOptions(['foobar', 'fizzbuzz'])) - .then(_dataKey => (dataKey = _dataKey)) - .then(() => - Promise.all([ - this.collection.findOne({ keyAltNames: 'foobar' }), - this.collection.findOne({ keyAltNames: 'fizzbuzz' }) - ]) - ) - .then(docs => { - expect(docs).to.have.lengthOf(2); - const doc1 = docs[0]; - const doc2 = docs[1]; - expect(doc1).to.be.an('object'); - expect(doc2).to.be.an('object'); - expect(doc1) - .to.have.property('keyAltNames') - .that.includes.members(['foobar', 'fizzbuzz']); - expect(doc1).to.have.property('_id').that.deep.equals(dataKey); - expect(doc2) - .to.have.property('keyAltNames') - .that.includes.members(['foobar', 'fizzbuzz']); - expect(doc2).to.have.property('_id').that.deep.equals(dataKey); - }); - }); - - it('should be able to reference a key with `keyAltName` during encryption', function () { - let keyId; - const keyAltName = 'mySpecialKey'; - const algorithm = 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'; - - const valueToEncrypt = 'foobar'; - - return this.encryption - .createDataKey('aws', makeOptions([keyAltName])) - .then(_dataKey => (keyId = _dataKey)) - .then(() => this.encryption.encrypt(valueToEncrypt, { keyId, algorithm })) - .then(encryptedValue => { - return this.encryption - .encrypt(valueToEncrypt, { keyAltName, algorithm }) - .then(encryptedValue2 => { - expect(encryptedValue).to.deep.equal(encryptedValue2); - }); - }); - }); - }); - - context('with stubbed key material and fixed random source', function () { - let sandbox = sinon.createSandbox(); - - afterEach(() => { - sandbox.restore(); - }); - beforeEach(() => { - const rndData = Buffer.from( - '\x4d\x06\x95\x64\xf5\xa0\x5e\x9e\x35\x23\xb9\x8f\x57\x5a\xcb\x15', - 'latin1' - ); - let rndPos = 0; - sandbox.stub(cryptoCallbacks, 'randomHook').callsFake((buffer, count) => { - if (rndPos + count > rndData) { - return new Error('Out of fake random data'); - } - buffer.set(rndData.subarray(rndPos, rndPos + count)); - rndPos += count; - return count; - }); - - // stubbed out for AWS unit testing below - sandbox.stub(StateMachine.prototype, 'fetchKeys').callsFake((client, ns, filter, cb) => { - filter = deserialize(filter); - const keyIds = filter.$or[0]._id.$in.map(key => key.toString('hex')); - const fileNames = keyIds.map( - keyId => `${__dirname}/../../../test/data/keys/${keyId.toUpperCase()}-local-document.json` - ); - const contents = fileNames.map(filename => EJSON.parse(fs.readFileSync(filename))); - cb(null, contents); - }); - }); - - // This exactly matches _test_encrypt_fle2_explicit from the C tests - it('should explicitly encrypt and decrypt with the "local" KMS provider (FLE2, exact result)', function () { - const encryption = new ClientEncryption(new MockClient(), { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: Buffer.alloc(96) } } - }); - - const encryptOptions = { - keyId: new Binary(Buffer.from('ABCDEFAB123498761234123456789012', 'hex'), 4), - algorithm: 'Unindexed' - }; - - return encryption - .encrypt('value123', encryptOptions) - .then(encrypted => { - expect(encrypted._bsontype).to.equal('Binary'); - expect(encrypted.sub_type).to.equal(6); - return encryption.decrypt(encrypted); - }) - .then(decrypted => { - expect(decrypted).to.equal('value123'); - }); - }); - }); - - describe('encrypt()', function () { - let clientEncryption; - let completeOptions; - let dataKey; - - beforeEach(async function () { - if (requirements.SKIP_LIVE_TESTS) { - this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; - this.test.skip(); - return; - } - - await setup(); - clientEncryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: Buffer.alloc(96) } } - }); - - dataKey = await clientEncryption.createDataKey('local', { - name: 'local', - kmsProviders: { local: { key: Buffer.alloc(96) } } - }); - - completeOptions = { - algorithm: 'RangePreview', - contentionFactor: 0, - rangeOptions: { - min: new BSON.Long(0), - max: new BSON.Long(10), - sparsity: new BSON.Long(1) - }, - keyId: dataKey - }; - }); - - afterEach(() => teardown()); - - context('when expressionMode is incorrectly provided as an argument', function () { - it('overrides the provided option with the correct value for expression mode', async function () { - const optionsWithExpressionMode = { ...completeOptions, expressionMode: true }; - const result = await clientEncryption.encrypt( - new mongodb.Long(0), - optionsWithExpressionMode - ); - - expect(result).to.be.instanceof(Binary); - }); - }); - }); - - describe('encryptExpression()', function () { - let clientEncryption; - let completeOptions; - let dataKey; - const expression = { - $and: [{ someField: { $gt: 1 } }] - }; - - beforeEach(async function () { - if (requirements.SKIP_LIVE_TESTS) { - this.currentTest.skipReason = `requirements.SKIP_LIVE_TESTS=${requirements.SKIP_LIVE_TESTS}`; - this.test.skip(); - return; - } - - await setup(); - clientEncryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: Buffer.alloc(96) } } - }); - - dataKey = await clientEncryption.createDataKey('local', { - name: 'local', - kmsProviders: { local: { key: Buffer.alloc(96) } } - }); - - completeOptions = { - algorithm: 'RangePreview', - queryType: 'rangePreview', - contentionFactor: 0, - rangeOptions: { - min: new BSON.Int32(0), - max: new BSON.Int32(10), - sparsity: new BSON.Long(1) - }, - keyId: dataKey - }; - }); - - afterEach(() => teardown()); - - it('throws if rangeOptions is not provided', async function () { - expect(delete completeOptions.rangeOptions).to.be.true; - const errorOrResult = await clientEncryption - .encryptExpression(expression, completeOptions) - .catch(e => e); - - expect(errorOrResult).to.be.instanceof(TypeError); - }); - - it('throws if algorithm is not provided', async function () { - expect(delete completeOptions.algorithm).to.be.true; - const errorOrResult = await clientEncryption - .encryptExpression(expression, completeOptions) - .catch(e => e); - - expect(errorOrResult).to.be.instanceof(TypeError); - }); - - it(`throws if algorithm does not equal 'rangePreview'`, async function () { - completeOptions['algorithm'] = 'equality'; - const errorOrResult = await clientEncryption - .encryptExpression(expression, completeOptions) - .catch(e => e); - - expect(errorOrResult).to.be.instanceof(TypeError); - }); - - it(`does not throw if algorithm has different casing than 'rangePreview'`, async function () { - completeOptions['algorithm'] = 'rAnGePrEvIeW'; - const errorOrResult = await clientEncryption - .encryptExpression(expression, completeOptions) - .catch(e => e); - - expect(errorOrResult).not.to.be.instanceof(Error); - }); - - context('when expressionMode is incorrectly provided as an argument', function () { - it('overrides the provided option with the correct value for expression mode', async function () { - const optionsWithExpressionMode = { ...completeOptions, expressionMode: false }; - const result = await clientEncryption.encryptExpression( - expression, - optionsWithExpressionMode - ); - - expect(result).not.to.be.instanceof(Binary); - }); - }); - }); - - it('should provide the libmongocrypt version', function () { - expect(ClientEncryption.libmongocryptVersion).to.be.a('string'); - }); - - describe('createEncryptedCollection()', () => { - /** @type {InstanceType} */ - let clientEncryption; - const client = new MockClient(); - let db; - const collectionName = 'secure'; - - beforeEach(async function () { - clientEncryption = new ClientEncryption(client, { - keyVaultNamespace: 'client.encryption', - kmsProviders: { local: { key: Buffer.alloc(96, 0) } } - }); - - db = client.db('createEncryptedCollectionDb'); - }); - - afterEach(async () => { - sinon.restore(); - }); - - context('validates input', () => { - it('throws TypeError if options are omitted', async () => { - const error = await clientEncryption - .createEncryptedCollection(db, collectionName) - .catch(error => error); - expect(error).to.be.instanceOf(TypeError, /provider/); - }); - - it('throws TypeError if options.createCollectionOptions are omitted', async () => { - const error = await clientEncryption - .createEncryptedCollection(db, collectionName, {}) - .catch(error => error); - expect(error).to.be.instanceOf(TypeError, /encryptedFields/); - }); - - it('throws TypeError if options.createCollectionOptions.encryptedFields are omitted', async () => { - const error = await clientEncryption - .createEncryptedCollection(db, collectionName, { createCollectionOptions: {} }) - .catch(error => error); - expect(error).to.be.instanceOf(TypeError, /Cannot read properties/); - }); - }); - - context('when options.encryptedFields.fields is not an array', () => { - it('does not generate any encryption keys', async () => { - const createCollectionSpy = sinon.spy(db, 'createCollection'); - const createDataKeySpy = sinon.spy(clientEncryption, 'createDataKey'); - await clientEncryption.createEncryptedCollection(db, collectionName, { - createCollectionOptions: { encryptedFields: { fields: 'not an array' } } - }); - - expect(createDataKeySpy.callCount).to.equal(0); - const options = createCollectionSpy.getCall(0).args[1]; - expect(options).to.deep.equal({ encryptedFields: { fields: 'not an array' } }); - }); - }); - - context('when options.encryptedFields.fields elements are not objects', () => { - it('they are passed along to createCollection', async () => { - const createCollectionSpy = sinon.spy(db, 'createCollection'); - const keyId = new Binary(Buffer.alloc(16, 0)); - const createDataKeyStub = sinon.stub(clientEncryption, 'createDataKey').resolves(keyId); - await clientEncryption.createEncryptedCollection(db, collectionName, { - createCollectionOptions: { - encryptedFields: { fields: ['not an array', { keyId: null }, { keyId: {} }] } - } - }); - - expect(createDataKeyStub.callCount).to.equal(1); - const options = createCollectionSpy.getCall(0).args[1]; - expect(options).to.deep.equal({ - encryptedFields: { fields: ['not an array', { keyId: keyId }, { keyId: {} }] } - }); - }); - }); - - it('only passes options.masterKey to createDataKey', async () => { - const masterKey = Symbol('key'); - const createDataKey = sinon - .stub(clientEncryption, 'createDataKey') - .resolves(new Binary(Buffer.alloc(16, 0))); - const result = await clientEncryption.createEncryptedCollection(db, collectionName, { - provider: 'aws', - createCollectionOptions: { encryptedFields: { fields: [{}] } }, - masterKey - }); - expect(result).to.have.property('collection'); - expect(createDataKey).to.have.been.calledOnceWithExactly('aws', { masterKey }); - }); - - context('when createDataKey rejects', () => { - const customErrorEvil = new Error('evil!'); - const customErrorGood = new Error('good!'); - const keyId = new Binary(Buffer.alloc(16, 0), 4); - const createCollectionOptions = { - encryptedFields: { fields: [{}, {}, { keyId: 'cool id!' }, {}] } - }; - const createDataKeyRejection = async () => { - const stub = sinon.stub(clientEncryption, 'createDataKey'); - stub.onCall(0).resolves(keyId); - stub.onCall(1).rejects(customErrorEvil); - stub.onCall(2).rejects(customErrorGood); - stub.onCall(4).resolves(keyId); - - const error = await clientEncryption - .createEncryptedCollection(db, collectionName, { - provider: 'local', - createCollectionOptions - }) - .catch(error => error); - - // At least make sure the function did not succeed - expect(error).to.be.instanceOf(Error); - - return error; - }; - - it('throws MongoCryptCreateDataKeyError', async () => { - const error = await createDataKeyRejection(); - expect(error).to.be.instanceOf(MongoCryptCreateDataKeyError); - }); - - it('thrown error has a cause set to the first error that was thrown from createDataKey', async () => { - const error = await createDataKeyRejection(); - expect(error.cause).to.equal(customErrorEvil); - expect(error.message).to.include(customErrorEvil.message); - }); - - it('thrown error contains partially filled encryptedFields.fields', async () => { - const error = await createDataKeyRejection(); - expect(error.encryptedFields).property('fields').that.is.an('array'); - expect(error.encryptedFields.fields).to.have.lengthOf( - createCollectionOptions.encryptedFields.fields.length - ); - expect(error.encryptedFields.fields).to.have.nested.property('[0].keyId', keyId); - expect(error.encryptedFields.fields).to.not.have.nested.property('[1].keyId'); - expect(error.encryptedFields.fields).to.have.nested.property('[2].keyId', 'cool id!'); - }); - }); - - context('when createCollection rejects', () => { - const customError = new Error('evil!'); - const keyId = new Binary(Buffer.alloc(16, 0), 4); - const createCollectionRejection = async () => { - const stubCreateDataKey = sinon.stub(clientEncryption, 'createDataKey'); - stubCreateDataKey.onCall(0).resolves(keyId); - stubCreateDataKey.onCall(1).resolves(keyId); - stubCreateDataKey.onCall(2).resolves(keyId); - - sinon.stub(db, 'createCollection').rejects(customError); - - const createCollectionOptions = { - encryptedFields: { fields: [{}, {}, { keyId: 'cool id!' }] } - }; - const error = await clientEncryption - .createEncryptedCollection(db, collectionName, { - provider: 'local', - createCollectionOptions - }) - .catch(error => error); - - // At least make sure the function did not succeed - expect(error).to.be.instanceOf(Error); - - return error; - }; - - it('throws MongoCryptCreateEncryptedCollectionError', async () => { - const error = await createCollectionRejection(); - expect(error).to.be.instanceOf(MongoCryptCreateEncryptedCollectionError); - }); - - it('thrown error has a cause set to the error that was thrown from createCollection', async () => { - const error = await createCollectionRejection(); - expect(error.cause).to.equal(customError); - expect(error.message).to.include(customError.message); - }); - - it('thrown error contains filled encryptedFields.fields', async () => { - const error = await createCollectionRejection(); - expect(error.encryptedFields).property('fields').that.is.an('array'); - expect(error.encryptedFields.fields).to.have.nested.property('[0].keyId', keyId); - expect(error.encryptedFields.fields).to.have.nested.property('[1].keyId', keyId); - expect(error.encryptedFields.fields).to.have.nested.property('[2].keyId', 'cool id!'); - }); - }); - - context('when there are nullish keyIds in the encryptedFields.fields array', function () { - it('does not mutate the input fields array when generating data keys', async () => { - const encryptedFields = Object.freeze({ - escCollection: 'esc', - eccCollection: 'ecc', - ecocCollection: 'ecoc', - fields: Object.freeze([ - Object.freeze({ keyId: false }), - Object.freeze({ - keyId: null, - path: 'name', - bsonType: 'int', - queries: Object.freeze({ contentionFactor: 0 }) - }), - null - ]) - }); - - const keyId = new Binary(Buffer.alloc(16, 0), 4); - sinon.stub(clientEncryption, 'createDataKey').resolves(keyId); - - const { collection, encryptedFields: resultEncryptedFields } = - await clientEncryption.createEncryptedCollection(db, collectionName, { - provider: 'local', - createCollectionOptions: { - encryptedFields - } - }); - - expect(collection).to.have.property('namespace', 'createEncryptedCollectionDb.secure'); - expect(encryptedFields, 'original encryptedFields should be unmodified').nested.property( - 'fields[0].keyId', - false - ); - expect( - resultEncryptedFields, - 'encryptedFields created by helper should have replaced nullish keyId' - ).nested.property('fields[1].keyId', keyId); - expect(encryptedFields, 'original encryptedFields should be unmodified').nested.property( - 'fields[2]', - null - ); - }); - - it('generates dataKeys for all null keyIds in the fields array', async () => { - const encryptedFields = Object.freeze({ - escCollection: 'esc', - eccCollection: 'ecc', - ecocCollection: 'ecoc', - fields: Object.freeze([ - Object.freeze({ keyId: null }), - Object.freeze({ keyId: null }), - Object.freeze({ keyId: null }) - ]) - }); - - const keyId = new Binary(Buffer.alloc(16, 0), 4); - sinon.stub(clientEncryption, 'createDataKey').resolves(keyId); - - const { collection, encryptedFields: resultEncryptedFields } = - await clientEncryption.createEncryptedCollection(db, collectionName, { - provider: 'local', - createCollectionOptions: { - encryptedFields - } - }); - - expect(collection).to.have.property('namespace', 'createEncryptedCollectionDb.secure'); - expect(resultEncryptedFields.fields).to.have.lengthOf(3); - expect(resultEncryptedFields.fields.filter(({ keyId }) => keyId === null)).to.have.lengthOf( - 0 - ); - }); - }); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/common.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/common.test.js deleted file mode 100644 index 7b1b7da..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/common.test.js +++ /dev/null @@ -1,94 +0,0 @@ -'use strict'; - -const { expect } = require('chai'); -const maybeCallback = require('../lib/common').maybeCallback; - -describe('maybeCallback()', () => { - it('should accept two arguments', () => { - expect(maybeCallback).to.have.lengthOf(2); - }); - - describe('when handling an error case', () => { - it('should pass the error to the callback provided', done => { - const superPromiseRejection = Promise.reject(new Error('fail')); - const result = maybeCallback( - () => superPromiseRejection, - (error, result) => { - try { - expect(result).to.not.exist; - expect(error).to.be.instanceOf(Error); - return done(); - } catch (assertionError) { - return done(assertionError); - } - } - ); - expect(result).to.be.undefined; - }); - - it('should return the rejected promise to the caller when no callback is provided', async () => { - const superPromiseRejection = Promise.reject(new Error('fail')); - const returnedPromise = maybeCallback(() => superPromiseRejection, undefined); - expect(returnedPromise).to.equal(superPromiseRejection); - // @ts-expect-error: There is no overload to change the return type not be nullish, - // and we do not want to add one in fear of making it too easy to neglect adding the callback argument - const thrownError = await returnedPromise.catch(error => error); - expect(thrownError).to.be.instanceOf(Error); - }); - - it('should not modify a rejection error promise', async () => { - class MyError extends Error {} - const driverError = Object.freeze(new MyError()); - const rejection = Promise.reject(driverError); - // @ts-expect-error: There is no overload to change the return type not be nullish, - // and we do not want to add one in fear of making it too easy to neglect adding the callback argument - const thrownError = await maybeCallback(() => rejection, undefined).catch(error => error); - expect(thrownError).to.be.equal(driverError); - }); - - it('should not modify a rejection error when passed to callback', done => { - class MyError extends Error {} - const driverError = Object.freeze(new MyError()); - const rejection = Promise.reject(driverError); - maybeCallback( - () => rejection, - error => { - try { - expect(error).to.exist; - expect(error).to.equal(driverError); - done(); - } catch (assertionError) { - done(assertionError); - } - } - ); - }); - }); - - describe('when handling a success case', () => { - it('should pass the result and undefined error to the callback provided', done => { - const superPromiseSuccess = Promise.resolve(2); - - const result = maybeCallback( - () => superPromiseSuccess, - (error, result) => { - try { - expect(error).to.be.undefined; - expect(result).to.equal(2); - done(); - } catch (assertionError) { - done(assertionError); - } - } - ); - expect(result).to.be.undefined; - }); - - it('should return the resolved promise to the caller when no callback is provided', async () => { - const superPromiseSuccess = Promise.resolve(2); - const result = maybeCallback(() => superPromiseSuccess); - expect(result).to.equal(superPromiseSuccess); - expect(await result).to.equal(2); - }); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/cryptoCallbacks.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/cryptoCallbacks.test.js deleted file mode 100644 index 941dfba..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/cryptoCallbacks.test.js +++ /dev/null @@ -1,240 +0,0 @@ -'use strict'; - -const sinon = require('sinon'); -const { expect } = require('chai'); -const mongodb = require('mongodb'); -const MongoClient = mongodb.MongoClient; -const stateMachine = require('../lib/stateMachine')({ mongodb }); -const cryptoCallbacks = require('../lib/cryptoCallbacks'); -const ClientEncryption = require('../lib/clientEncryption')({ - mongodb, - stateMachine -}).ClientEncryption; - -const requirements = require('./requirements.helper'); - -// Data Key Stuff -const kmsProviders = Object.assign({}, requirements.awsKmsProviders); -const dataKeyOptions = Object.assign({}, requirements.awsDataKeyOptions); - -describe('cryptoCallbacks', function () { - before(function () { - if (requirements.SKIP_AWS_TESTS) { - console.error('Skipping crypto callback tests'); - return; - } - this.sinon = sinon.createSandbox(); - }); - - beforeEach(function () { - if (requirements.SKIP_AWS_TESTS) { - this.currentTest.skipReason = `requirements.SKIP_AWS_TESTS=${requirements.SKIP_AWS_TESTS}`; - this.test.skip(); - return; - } - this.sinon.restore(); - this.client = new MongoClient('mongodb://localhost:27017/', { - useUnifiedTopology: true, - useNewUrlParser: true - }); - - return this.client.connect(); - }); - - afterEach(function () { - if (requirements.SKIP_AWS_TESTS) { - return; - } - this.sinon.restore(); - let p = Promise.resolve(); - if (this.client) { - p = p.then(() => this.client.close()).then(() => (this.client = undefined)); - } - - return p; - }); - - after(function () { - this.sinon = undefined; - }); - - // TODO(NODE-3370): fix key formatting error "asn1_check_tlen:wrong tag" - it.skip('should support support crypto callback for signing RSA-SHA256', function () { - const input = Buffer.from('data to sign'); - const pemFileData = - '-----BEGIN PRIVATE KEY-----\n' + - 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4JOyv5z05cL18ztpknRC7CFY2gYol4DAKerdVUoDJxCTmFMf39dVUEqD0WDiw/qcRtSO1/FRut08PlSPmvbyKetsLoxlpS8lukSzEFpFK7+L+R4miFOl6HvECyg7lbC1H/WGAhIz9yZRlXhRo9qmO/fB6PV9IeYtU+1xYuXicjCDPp36uuxBAnCz7JfvxJ3mdVc0vpSkbSb141nWuKNYR1mgyvvL6KzxO6mYsCo4hRAdhuizD9C4jDHk0V2gDCFBk0h8SLEdzStX8L0jG90/Og4y7J1b/cPo/kbYokkYisxe8cPlsvGBf+rZex7XPxc1yWaP080qeABJb+S88O//LAgMBAAECggEBAKVxP1m3FzHBUe2NZ3fYCc0Qa2zjK7xl1KPFp2u4CU+9sy0oZJUqQHUdm5CMprqWwIHPTftWboFenmCwrSXFOFzujljBO7Z3yc1WD3NJl1ZNepLcsRJ3WWFH5V+NLJ8Bdxlj1DMEZCwr7PC5+vpnCuYWzvT0qOPTl9RNVaW9VVjHouJ9Fg+s2DrShXDegFabl1iZEDdI4xScHoYBob06A5lw0WOCTayzw0Naf37lM8Y4psRAmI46XLiF/Vbuorna4hcChxDePlNLEfMipICcuxTcei1RBSlBa2t1tcnvoTy6cuYDqqImRYjp1KnMKlKQBnQ1NjS2TsRGm+F0FbreVCECgYEA4IDJlm8q/hVyNcPe4OzIcL1rsdYN3bNm2Y2O/YtRPIkQ446ItyxD06d9VuXsQpFp9jNACAPfCMSyHpPApqlxdc8z/xATlgHkcGezEOd1r4E7NdTpGg8y6Rj9b8kVlED6v4grbRhKcU6moyKUQT3+1B6ENZTOKyxuyDEgTwZHtFECgYEA0fqdv9h9s77d6eWmIioP7FSymq93pC4umxf6TVicpjpMErdD2ZfJGulN37dq8FOsOFnSmFYJdICj/PbJm6p1i8O21lsFCltEqVoVabJ7/0alPfdG2U76OeBqI8ZubL4BMnWXAB/VVEYbyWCNpQSDTjHQYs54qa2I0dJB7OgJt1sCgYEArctFQ02/7H5Rscl1yo3DBXO94SeiCFSPdC8f2Kt3MfOxvVdkAtkjkMACSbkoUsgbTVqTYSEOEc2jTgR3iQ13JgpHaFbbsq64V0QP3TAxbLIQUjYGVgQaF1UfLOBv8hrzgj45z/ST/G80lOl595+0nCUbmBcgG1AEWrmdF0/3RmECgYAKvIzKXXB3+19vcT2ga5Qq2l3TiPtOGsppRb2XrNs9qKdxIYvHmXo/9QP1V3SRW0XoD7ez8FpFabp42cmPOxUNk3FK3paQZABLxH5pzCWI9PzIAVfPDrm+sdnbgG7vAnwfL2IMMJSA3aDYGCbF9EgefG+STcpfqq7fQ6f5TBgLFwKBgCd7gn1xYL696SaKVSm7VngpXlczHVEpz3kStWR5gfzriPBxXgMVcWmcbajRser7ARpCEfbxM1UJyv6oAYZWVSNErNzNVb4POqLYcCNySuC6xKhs9FrEQnyKjyk8wI4VnrEMGrQ8e+qYSwYk9Gh6dKGoRMAPYVXQAO0fIsHF/T0a\n' + - '-----END PRIVATE KEY-----'; - const key = Buffer.from(pemFileData); - const output = Buffer.alloc(256); - const expectedOutput = Buffer.from( - 'VocBRhpMmQ2XCzVehWSqheQLnU889gf3dhU4AnVnQTJjsKx/CM23qKDPkZDd2A/BnQsp99SN7ksIX5Raj0TPwyN5OCN/YrNFNGoOFlTsGhgP/hyE8X3Duiq6sNO0SMvRYNPFFGlJFsp1Fw3Z94eYMg4/Wpw5s4+Jo5Zm/qY7aTJIqDKDQ3CNHLeJgcMUOc9sz01/GzoUYKDVODHSxrYEk5ireFJFz9vP8P7Ha+VDUZuQIQdXer9NBbGFtYmWprY3nn4D3Dw93Sn0V0dIqYeIo91oKyslvMebmUM95S2PyIJdEpPb2DJDxjvX/0LLwSWlSXRWy9gapWoBkb4ynqZBsg==', - 'base64' - ); - - const { signRsaSha256Hook } = cryptoCallbacks; - const err = signRsaSha256Hook(key, input, output); - if (err instanceof Error) { - expect(err).to.not.exist; - } - - expect(output).to.deep.equal(expectedOutput); - }).skipReason = 'TODO(NODE-3370): fix key formatting error "asn1_check_tlen:wrong tag"'; - - const hookNames = new Set([ - 'aes256CbcEncryptHook', - 'aes256CbcDecryptHook', - 'randomHook', - 'hmacSha512Hook', - 'hmacSha256Hook', - 'sha256Hook' - ]); - - it('should invoke crypto callbacks when doing encryption', function (done) { - for (const name of hookNames) { - this.sinon.spy(cryptoCallbacks, name); - } - - function assertCertainHooksCalled(expectedSet) { - expectedSet = expectedSet || new Set([]); - for (const name of hookNames) { - const hook = cryptoCallbacks[name]; - if (expectedSet.has(name)) { - expect(hook).to.have.been.called; - } else { - expect(hook).to.not.have.been.called; - } - - hook.resetHistory(); - } - } - - const encryption = new ClientEncryption(this.client, { - keyVaultNamespace: 'test.encryption', - kmsProviders - }); - - try { - assertCertainHooksCalled(); - } catch (e) { - return done(e); - } - - encryption.createDataKey('aws', dataKeyOptions, (err, dataKey) => { - try { - expect(err).to.not.exist; - assertCertainHooksCalled(new Set(['hmacSha256Hook', 'sha256Hook', 'randomHook'])); - } catch (e) { - return done(e); - } - - const encryptOptions = { - keyId: dataKey, - algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' - }; - - encryption.encrypt('hello', encryptOptions, (err, encryptedValue) => { - try { - expect(err).to.not.exist; - assertCertainHooksCalled( - new Set(['aes256CbcEncryptHook', 'hmacSha512Hook', 'hmacSha256Hook', 'sha256Hook']) - ); - } catch (e) { - return done(e); - } - encryption.decrypt(encryptedValue, err => { - try { - expect(err).to.not.exist; - assertCertainHooksCalled(new Set(['aes256CbcDecryptHook', 'hmacSha512Hook'])); - } catch (e) { - return done(e); - } - done(); - }); - }); - }); - }); - - describe('error testing', function () { - ['aes256CbcEncryptHook', 'aes256CbcDecryptHook', 'hmacSha512Hook'].forEach(hookName => { - it(`should properly propagate an error when ${hookName} fails`, function (done) { - const error = new Error('some random error text'); - this.sinon.stub(cryptoCallbacks, hookName).returns(error); - - const encryption = new ClientEncryption(this.client, { - keyVaultNamespace: 'test.encryption', - kmsProviders - }); - - function finish(err) { - try { - expect(err, 'Expected an error to exist').to.exist; - expect(err).to.have.property('message', error.message); - done(); - } catch (e) { - done(e); - } - } - - try { - encryption.createDataKey('aws', dataKeyOptions, (err, dataKey) => { - if (err) return finish(err); - - const encryptOptions = { - keyId: dataKey, - algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' - }; - - encryption.encrypt('hello', encryptOptions, (err, encryptedValue) => { - if (err) return finish(err); - encryption.decrypt(encryptedValue, err => finish(err)); - }); - }); - } catch (e) { - done(new Error('We should not be here')); - } - }); - }); - - // These ones will fail with an error, but that error will get overridden - // with "failed to create KMS message" in mongocrypt-kms-ctx.c - ['hmacSha256Hook', 'sha256Hook'].forEach(hookName => { - it(`should error with a specific kms error when ${hookName} fails`, function () { - const error = new Error('some random error text'); - this.sinon.stub(cryptoCallbacks, hookName).returns(error); - - const encryption = new ClientEncryption(this.client, { - keyVaultNamespace: 'test.encryption', - kmsProviders - }); - - expect(() => encryption.createDataKey('aws', dataKeyOptions, () => undefined)).to.throw( - 'failed to create KMS message' - ); - }); - }); - - it('should error synchronously with error when randomHook fails', function (done) { - const error = new Error('some random error text'); - this.sinon.stub(cryptoCallbacks, 'randomHook').returns(error); - - const encryption = new ClientEncryption(this.client, { - keyVaultNamespace: 'test.encryption', - kmsProviders - }); - - try { - encryption.createDataKey('aws', dataKeyOptions, () => { - done(new Error('We should not be here')); - }); - } catch (err) { - try { - expect(err).to.have.property('message', 'some random error text'); - done(); - } catch (e) { - done(e); - } - } - }); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/README.md b/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/README.md deleted file mode 100644 index c7f47ca..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# libmongocrypt example data # - -This directory contains a simple example of mocked responses to test libmongocrypt and driver wrappers. Data for other scenarios and edge cases is in the `data` directory. - -The HTTP reply file, kms-decrypt-reply.txt, has regular newline endings \n that MUST be replaced by \r\n endings when reading the file for testing. \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/cmd.json b/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/cmd.json deleted file mode 100644 index 0fa3fee..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/cmd.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "find": "test", - "filter": { - "ssn": "457-55-5462" - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/collection-info.json b/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/collection-info.json deleted file mode 100644 index 063e32b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/collection-info.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "type": "collection", - "name": "test", - "idIndex": { - "ns": "test.test", - "name": "_id_", - "key": { - "_id": { - "$numberInt": "1" - } - }, - "v": { - "$numberInt": "2" - } - }, - "options": { - "validator": { - "$jsonSchema": { - "properties": { - "ssn": { - "encrypt": { - "keyId": { - "$binary": { - "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", - "subType": "04" - } - }, - "type": "string", - "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" - } - } - }, - "bsonType": "object" - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/encrypted-document-nested.json b/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/encrypted-document-nested.json deleted file mode 100644 index bd02d07..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/encrypted-document-nested.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "nested": { - "$binary": { - "base64": "AmFhYWFhYWFhYWFhYWFhYWEDW89+etsVGIufAfsiEwR62ce6+lry79sJJBUyJ6hH89wBkhpRkzFLz26Nu6jXQRe8ESYAF5cAa5wg9rsq95IBHuaIaLEQLW2jLjGo1fp69jg=", - "subType": "06" - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/encrypted-document.json b/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/encrypted-document.json deleted file mode 100644 index 98b2c5b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/encrypted-document.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "filter": { - "find": "test", - "ssn": { - "$binary": { - "base64": "AWFhYWFhYWFhYWFhYWFhYWECRTOW9yZzNDn5dGwuqsrJQNLtgMEKaujhs9aRWRp+7Yo3JK8N8jC8P0Xjll6C1CwLsE/iP5wjOMhVv1KMMyOCSCrHorXRsb2IKPtzl2lKTqQ=", - "subType": "06" - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/encryptedFields.json b/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/encryptedFields.json deleted file mode 100644 index 07a29ed..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/encryptedFields.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "fields": [ - { - "keyId": { - "$binary": { - "base64": "EjRWeBI0mHYSNBI0VniQEg==", - "subType": "04" - } - }, - "path": "encryptedIndexed", - "bsonType": "string", - "queries": { - "queryType": "equality", - "contention": { - "$numberLong": "0" - } - } - }, - { - "keyId": { - "$binary": { - "base64": "q83vqxI0mHYSNBI0VniQEg==", - "subType": "04" - } - }, - "path": "encryptedUnindexed", - "bsonType": "string" - } - ] -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/key-document.json b/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/key-document.json deleted file mode 100644 index 647963f..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/key-document.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "status": { - "$numberInt": "1" - }, - "_id": { - "$binary": { - "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", - "subType": "04" - } - }, - "masterKey": { - "region": "us-east-1", - "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", - "provider": "aws" - }, - "updateDate": { - "$date": { - "$numberLong": "1557827033449" - } - }, - "keyMaterial": { - "$binary": { - "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", - "subType": "00" - } - }, - "creationDate": { - "$date": { - "$numberLong": "1557827033449" - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/key1-document.json b/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/key1-document.json deleted file mode 100644 index 566b56c..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/key1-document.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "_id": { - "$binary": { - "base64": "EjRWeBI0mHYSNBI0VniQEg==", - "subType": "04" - } - }, - "keyMaterial": { - "$binary": { - "base64": "sHe0kz57YW7v8g9VP9sf/+K1ex4JqKc5rf/URX3n3p8XdZ6+15uXPaSayC6adWbNxkFskuMCOifDoTT+rkqMtFkDclOy884RuGGtUysq3X7zkAWYTKi8QAfKkajvVbZl2y23UqgVasdQu3OVBQCrH/xY00nNAs/52e958nVjBuzQkSb1T8pKJAyjZsHJ60+FtnfafDZSTAIBJYn7UWBCwQ==", - "subType": "00" - } - }, - "creationDate": { - "$date": { - "$numberLong": "1648914851981" - } - }, - "updateDate": { - "$date": { - "$numberLong": "1648914851981" - } - }, - "status": { - "$numberInt": "0" - }, - "masterKey": { - "provider": "local" - } -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/mongocryptd-reply.json b/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/mongocryptd-reply.json deleted file mode 100644 index 9d03814..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/mongocryptd-reply.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "schemaRequiresEncryption": true, - "ok": { - "$numberInt": "1" - }, - "result": { - "filter": { - "ssn": { - "$binary": { - "base64": "ADgAAAAQYQABAAAABWtpABAAAAAEYWFhYWFhYWFhYWFhYWFhYQJ2AAwAAAA0NTctNTUtNTQ2MgAA", - "subType": "06" - } - } - }, - "find": "test" - }, - "hasEncryptedPlaceholders": true -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/index.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/index.test.js deleted file mode 100644 index 188a236..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/index.test.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -const { expect } = require('chai'); -const mongodbClientEncryption = require('../lib/index'); -const { fetchAzureKMSToken } = require('../lib/providers'); - -// Update this as you add exports, helps double check we don't accidentally remove something -// since not all tests import from the root public export -const EXPECTED_EXPORTS = [ - 'extension', - 'MongoCryptError', - 'MongoCryptCreateEncryptedCollectionError', - 'MongoCryptCreateDataKeyError', - 'MongoCryptAzureKMSRequestError', - 'MongoCryptKMSRequestNetworkTimeoutError', - 'AutoEncrypter', - 'ClientEncryption' -]; - -describe('mongodb-client-encryption entrypoint', () => { - it('should export all and only the expected keys in expected_exports', () => { - expect(mongodbClientEncryption).to.have.all.keys(EXPECTED_EXPORTS); - }); - - it('extension returns an object equal in shape to the default except for extension', () => { - const extensionResult = mongodbClientEncryption.extension(require('mongodb')); - const expectedExports = EXPECTED_EXPORTS.filter(exp => exp !== 'extension'); - const exportsDefault = Object.keys(mongodbClientEncryption).filter(exp => exp !== 'extension'); - expect(extensionResult).to.have.all.keys(expectedExports); - expect(extensionResult).to.have.all.keys(exportsDefault); - }); - - context('exports for driver testing', () => { - it('exports `fetchAzureKMSToken` in a symbol property', () => { - expect(mongodbClientEncryption).to.have.property( - '___azureKMSProseTestExports', - fetchAzureKMSToken - ); - }); - it('extension exports `fetchAzureKMSToken` in a symbol property', () => { - const extensionResult = mongodbClientEncryption.extension(require('mongodb')); - expect(extensionResult).to.have.property('___azureKMSProseTestExports', fetchAzureKMSToken); - }); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/mongocryptdManager.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/mongocryptdManager.test.js deleted file mode 100644 index 17f8687..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/mongocryptdManager.test.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -const MongocryptdManager = require('../lib/mongocryptdManager').MongocryptdManager; -const { expect } = require('chai'); - -describe('MongocryptdManager', function () { - it('should default to having spawnArgs of --idleShutdownTimeoutSecs=60', function () { - const mcdm = new MongocryptdManager(); - expect(mcdm.spawnArgs).to.deep.equal(['--idleShutdownTimeoutSecs', 60]); - }); - - it('should concat --idleShutdownTimeoutSecs=60 to provided args', function () { - const mcdm = new MongocryptdManager({ mongocryptdSpawnArgs: ['foo', 12] }); - expect(mcdm.spawnArgs).to.deep.equal(['foo', 12, '--idleShutdownTimeoutSecs', 60]); - }); - - it('should not override `idleShutdownTimeoutSecs` if the user sets it using `key value` form', function () { - const mcdm = new MongocryptdManager({ - mongocryptdSpawnArgs: ['--idleShutdownTimeoutSecs', 12] - }); - - expect(mcdm.spawnArgs).to.deep.equal(['--idleShutdownTimeoutSecs', 12]); - }); - - it('should not override `idleShutdownTimeoutSecs` if the user sets it using `key=value` form', function () { - const mcdm = new MongocryptdManager({ - mongocryptdSpawnArgs: ['--idleShutdownTimeoutSecs=12'] - }); - - expect(mcdm.spawnArgs).to.deep.equal(['--idleShutdownTimeoutSecs=12']); - }); - - it('should support construction with options', function () { - const mcdm = new MongocryptdManager({ - mongocryptdURI: 'some-uri', - mongocryptdBypassSpawn: true, - mongocryptdSpawnPath: 'some-spawn-path', - mongocryptdSpawnArgs: ['--idleShutdownTimeoutSecs=12'] - }); - - expect(mcdm).to.eql({ - uri: 'some-uri', - bypassSpawn: true, - spawnPath: 'some-spawn-path', - spawnArgs: ['--idleShutdownTimeoutSecs=12'] - }); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/providers/credentialsProvider.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/providers/credentialsProvider.test.js deleted file mode 100644 index 30de32b..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/providers/credentialsProvider.test.js +++ /dev/null @@ -1,551 +0,0 @@ -'use strict'; - -const { expect } = require('chai'); -const http = require('http'); -const requirements = require('../requirements.helper'); -const { loadCredentials, isEmptyCredentials } = require('../../lib/providers'); -const { tokenCache, fetchAzureKMSToken } = require('../../lib/providers/azure'); -const sinon = require('sinon'); -const utils = require('../../lib/providers/utils'); -const { - MongoCryptKMSRequestNetworkTimeoutError, - MongoCryptAzureKMSRequestError -} = require('../../lib/errors'); - -const originalAccessKeyId = process.env.AWS_ACCESS_KEY_ID; -const originalSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; -const originalSessionToken = process.env.AWS_SESSION_TOKEN; - -describe('#loadCredentials', function () { - context('isEmptyCredentials()', () => { - it('returns true for an empty object', () => { - expect(isEmptyCredentials('rainyCloud', { rainyCloud: {} })).to.be.true; - }); - - it('returns false for an object with keys', () => { - expect(isEmptyCredentials('rainyCloud', { rainyCloud: { password: 'secret' } })).to.be.false; - }); - - it('returns false for an nullish credentials', () => { - expect(isEmptyCredentials('rainyCloud', { rainyCloud: null })).to.be.false; - expect(isEmptyCredentials('rainyCloud', { rainyCloud: undefined })).to.be.false; - expect(isEmptyCredentials('rainyCloud', {})).to.be.false; - }); - - it('returns false for non object credentials', () => { - expect(isEmptyCredentials('rainyCloud', { rainyCloud: 0 })).to.be.false; - expect(isEmptyCredentials('rainyCloud', { rainyCloud: false })).to.be.false; - expect(isEmptyCredentials('rainyCloud', { rainyCloud: Symbol('secret') })).to.be.false; - }); - }); - - context('when using aws', () => { - const accessKey = 'example'; - const secretKey = 'example'; - const sessionToken = 'example'; - - after(function () { - // After the entire suite runs, set the env back for the rest of the test run. - process.env.AWS_ACCESS_KEY_ID = originalAccessKeyId; - process.env.AWS_SECRET_ACCESS_KEY = originalSecretAccessKey; - process.env.AWS_SESSION_TOKEN = originalSessionToken; - }); - - context('when the credential provider finds credentials', function () { - before(function () { - process.env.AWS_ACCESS_KEY_ID = accessKey; - process.env.AWS_SECRET_ACCESS_KEY = secretKey; - process.env.AWS_SESSION_TOKEN = sessionToken; - }); - - context('when the credentials are empty', function () { - const kmsProviders = { aws: {} }; - - before(function () { - if (!requirements.credentialProvidersInstalled.aws) { - this.currentTest.skipReason = 'Cannot refresh credentials without sdk provider'; - this.currentTest.skip(); - return; - } - }); - - it('refreshes the aws credentials', async function () { - const providers = await loadCredentials(kmsProviders); - expect(providers).to.deep.equal({ - aws: { - accessKeyId: accessKey, - secretAccessKey: secretKey, - sessionToken: sessionToken - } - }); - }); - }); - - context('when the credentials are not empty', function () { - context('when aws is empty', function () { - const kmsProviders = { - local: { - key: Buffer.alloc(96) - }, - aws: {} - }; - - before(function () { - if (!requirements.credentialProvidersInstalled.aws) { - this.currentTest.skipReason = 'Cannot refresh credentials without sdk provider'; - this.currentTest.skip(); - return; - } - }); - - it('refreshes only the aws credentials', async function () { - const providers = await loadCredentials(kmsProviders); - expect(providers).to.deep.equal({ - local: { - key: Buffer.alloc(96) - }, - aws: { - accessKeyId: accessKey, - secretAccessKey: secretKey, - sessionToken: sessionToken - } - }); - }); - }); - - context('when aws is not empty', function () { - const kmsProviders = { - local: { - key: Buffer.alloc(96) - }, - aws: { - accessKeyId: 'example' - } - }; - - before(function () { - if (!requirements.credentialProvidersInstalled.aws) { - this.currentTest.skipReason = 'Cannot refresh credentials without sdk provider'; - this.currentTest.skip(); - return; - } - }); - - it('does not refresh credentials', async function () { - const providers = await loadCredentials(kmsProviders); - expect(providers).to.deep.equal(kmsProviders); - }); - }); - }); - }); - - context('when the sdk is not installed', function () { - const kmsProviders = { - local: { - key: Buffer.alloc(96) - }, - aws: {} - }; - - before(function () { - if (requirements.credentialProvidersInstalled.aws) { - this.currentTest.skipReason = 'Credentials will be loaded when sdk present'; - this.currentTest.skip(); - return; - } - }); - - it('does not refresh credentials', async function () { - const providers = await loadCredentials(kmsProviders); - expect(providers).to.deep.equal(kmsProviders); - }); - }); - }); - - context('when using gcp', () => { - const setupHttpServer = status => { - let httpServer; - before(() => { - httpServer = http - .createServer((_, res) => { - if (status === 200) { - res.writeHead(200, { 'Content-Type': 'application/json' }); - res.writeHead(200, { 'Metadata-Flavor': 'Google' }); - res.end(JSON.stringify({ access_token: 'abc' })); - } else { - res.writeHead(401, { 'Content-Type': 'application/json' }); - res.writeHead(401, { 'Metadata-Flavor': 'Google' }); - res.end('{}'); - } - }) - .listen(5001); - process.env.GCE_METADATA_HOST = 'http://127.0.0.1:5001'; - }); - - after(() => { - httpServer.close(); - delete process.env.GCE_METADATA_HOST; - }); - }; - - context('and gcp-metadata is installed', () => { - beforeEach(function () { - if (!requirements.credentialProvidersInstalled.gcp) { - this.currentTest.skipReason = 'Tests require gcp-metadata to be installed'; - this.currentTest.skip(); - return; - } - }); - - context('when metadata http response is 200 ok', () => { - setupHttpServer(200); - context('when the credentials are empty', function () { - const kmsProviders = { gcp: {} }; - - it('refreshes the gcp credentials', async function () { - const providers = await loadCredentials(kmsProviders); - expect(providers).to.deep.equal({ - gcp: { - accessToken: 'abc' - } - }); - }); - }); - }); - - context('when metadata http response is 401 bad', () => { - setupHttpServer(401); - context('when the credentials are empty', function () { - const kmsProviders = { gcp: {} }; - - it('surfaces error from server', async function () { - const error = await loadCredentials(kmsProviders).catch(error => error); - expect(error).to.be.instanceOf(Error); - }); - }); - }); - }); - - context('and gcp-metadata is not installed', () => { - beforeEach(function () { - if (requirements.credentialProvidersInstalled.gcp) { - this.currentTest.skipReason = 'Tests require gcp-metadata to be installed'; - this.currentTest.skip(); - return; - } - }); - - context('when the credentials are empty', function () { - const kmsProviders = { gcp: {} }; - - it('does not modify the gcp credentials', async function () { - const providers = await loadCredentials(kmsProviders); - expect(providers).to.deep.equal({ gcp: {} }); - }); - }); - }); - }); - - context('when using azure', () => { - afterEach(() => tokenCache.resetCache()); - afterEach(() => sinon.restore()); - context('credential caching', () => { - const cache = tokenCache; - - beforeEach(() => { - cache.resetCache(); - }); - - context('when there is no cached token', () => { - let mockToken = { - accessToken: 'mock token', - expiresOnTimestamp: Date.now() - }; - - let token; - - beforeEach(async () => { - sinon.stub(cache, '_getToken').returns(mockToken); - token = await cache.getToken(); - }); - it('fetches a token', async () => { - expect(token).to.have.property('accessToken', mockToken.accessToken); - }); - it('caches the token on the class', async () => { - expect(cache.cachedToken).to.equal(mockToken); - }); - }); - - context('when there is a cached token', () => { - context('when the cached token expires <= 1 minute from the current time', () => { - let mockToken = { - accessToken: 'mock token', - expiresOnTimestamp: Date.now() - }; - - let token; - - beforeEach(async () => { - cache.cachedToken = { - accessToken: 'a new key', - expiresOnTimestamp: Date.now() + 3000 - }; - sinon.stub(cache, '_getToken').returns(mockToken); - token = await cache.getToken(); - }); - - it('fetches a token', () => { - expect(token).to.have.property('accessToken', mockToken.accessToken); - }); - it('caches the token on the class', () => { - expect(cache.cachedToken).to.equal(mockToken); - }); - }); - - context('when the cached token expires > 1 minute from the current time', () => { - let expiredToken = { - token: 'mock token', - expiresOnTimestamp: Date.now() - }; - - let expectedMockToken = { - accessToken: 'a new key', - expiresOnTimestamp: Date.now() + 10000 - }; - - let token; - - beforeEach(async () => { - cache.cachedToken = expiredToken; - sinon.stub(cache, '_getToken').returns(expectedMockToken); - token = await cache.getToken(); - }); - it('returns the cached token', () => { - expect(token).to.have.property('accessToken', expectedMockToken.accessToken); - }); - }); - }); - }); - - context('request configuration', () => { - const mockResponse = { - status: 200, - body: '{ "access_token": "token", "expires_in": "10000" }' - }; - - let httpSpy; - - beforeEach(async () => { - httpSpy = sinon.stub(utils, 'get'); - httpSpy.resolves(mockResponse); - - await loadCredentials({ azure: {} }); - }); - - it('sets the `api-version` param to 2012-02-01', () => { - const url = httpSpy.args[0][0]; - expect(url).to.be.instanceof(URL); - expect(url.searchParams.get('api-version'), '2018-02-01'); - }); - - it('sets the `resource` param to `https://vault.azure.net`', () => { - const url = httpSpy.args[0][0]; - expect(url).to.be.instanceof(URL); - expect(url.searchParams.get('resource'), 'https://vault.azure.net'); - }); - - it('sends the request to `http://169.254.169.254/metadata/identity/oauth2/token`', () => { - const url = httpSpy.args[0][0]; - expect(url).to.be.instanceof(URL); - expect(url.toString()).to.include('http://169.254.169.254/metadata/identity/oauth2/token'); - }); - - it('sets the Metadata header to true', () => { - const options = httpSpy.args[0][1]; - expect(options).to.have.property('headers').to.have.property('Metadata', true); - }); - - it('sets the Content-Type header to application/json', () => { - const options = httpSpy.args[0][1]; - expect(options) - .to.have.property('headers') - .to.have.property('Content-Type', 'application/json'); - }); - - context('prose test specific requirements', () => { - /** - * the driver prose tests require the ability to set custom URL endpoints - * for the IMDS call and set custom headers - */ - const url = new URL('http://customentpoint.com'); - - beforeEach(async () => { - sinon.restore(); - httpSpy = sinon.stub(utils, 'get'); - httpSpy.resolves(mockResponse); - await fetchAzureKMSToken({ - url, - headers: { - customHeader1: 'value1', - customHeader2: 'value2' - } - }); - }); - - it('allows a custom URL to be specified', () => { - const url = httpSpy.args[0][0]; - expect(url).to.be.instanceof(URL); - expect(url.toString()).to.include('http://customentpoint.com'); - }); - - it('deep copies the provided url', () => { - const spiedUrl = httpSpy.args[0][0]; - expect(spiedUrl).to.be.instanceof(URL); - expect(spiedUrl).to.not.equal(url); - }); - - it('allows custom headers to be specified', () => { - const options = httpSpy.args[0][1]; - expect(options).to.have.property('headers').to.have.property('customHeader1', 'value1'); - expect(options).to.have.property('headers').to.have.property('customHeader2', 'value2'); - }); - }); - }); - - context('error handling', () => { - afterEach(() => sinon.restore()); - context('when the request times out', () => { - before(() => { - sinon.stub(utils, 'get').rejects(new MongoCryptKMSRequestNetworkTimeoutError()); - }); - - it('throws a MongoCryptKMSRequestError', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); - }); - }); - - context('when the request returns a non-200 error', () => { - context('when the request has no body', () => { - before(() => { - sinon.stub(utils, 'get').resolves({ status: 400 }); - }); - - it('throws a MongoCryptKMSRequestError', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); - expect(error).to.match(/Malformed JSON body in GET request/); - }); - }); - - context('when the request has a non-json body', () => { - before(() => { - sinon.stub(utils, 'get').resolves({ status: 400, body: 'non-json body' }); - }); - - it('throws a MongoCryptKMSRequestError', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); - expect(error).to.match(/Malformed JSON body in GET request/); - }); - }); - - context('when the request has a json body', () => { - beforeEach(() => { - sinon - .stub(utils, 'get') - .resolves({ status: 400, body: '{ "error": "something went wrong" }' }); - }); - - it('throws a MongoCryptKMSRequestError', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); - }); - - it('attaches the body to the error', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.have.property('body').to.deep.equal({ error: 'something went wrong' }); - }); - }); - }); - - context('when the request returns a 200 response', () => { - context('when the request has no body', () => { - before(() => { - sinon.stub(utils, 'get').resolves({ status: 200 }); - }); - - it('throws a MongoCryptKMSRequestError', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); - expect(error).to.match(/Malformed JSON body in GET request/); - }); - }); - - context('when the request has a non-json body', () => { - before(() => { - sinon.stub(utils, 'get').resolves({ status: 200, body: 'non-json body' }); - }); - - it('throws a MongoCryptKMSRequestError', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); - expect(error).to.match(/Malformed JSON body in GET request/); - }); - }); - - context('when the body has no access_token', () => { - beforeEach(() => { - sinon.stub(utils, 'get').resolves({ status: 200, body: '{ "expires_in": "10000" }' }); - }); - - it('throws a MongoCryptKMSRequestError', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); - expect(error).to.match(/missing field `access_token/); - }); - }); - - context('when the body has no expires_in', () => { - beforeEach(() => { - sinon.stub(utils, 'get').resolves({ status: 200, body: '{ "access_token": "token" }' }); - }); - - it('throws a MongoCryptKMSRequestError', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); - expect(error).to.match(/missing field `expires_in/); - }); - }); - - context('when expires_in cannot be parsed into a number', () => { - beforeEach(() => { - sinon.stub(utils, 'get').resolves({ - status: 200, - body: '{ "access_token": "token", "expires_in": "foo" }' - }); - }); - - it('throws a MongoCryptKMSRequestError', async () => { - const error = await loadCredentials({ azure: {} }).catch(e => e); - expect(error).to.be.instanceOf(MongoCryptAzureKMSRequestError); - expect(error).to.match(/unable to parse int from `expires_in` field/); - }); - }); - }); - - context('when a valid token was returned', () => { - beforeEach(() => { - sinon - .stub(utils, 'get') - .resolves({ status: 200, body: '{ "access_token": "token", "expires_in": "10000" }' }); - }); - - it('returns the token in the `azure` field of the kms providers', async () => { - const kmsProviders = await loadCredentials({ azure: {} }); - expect(kmsProviders).to.have.property('azure').to.deep.equal({ accessToken: 'token' }); - }); - }); - }); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/release.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/release.test.js deleted file mode 100644 index caaecf5..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/release.test.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; -const { expect } = require('chai'); -const tar = require('tar'); -const cp = require('child_process'); -const fs = require('fs'); -const pkg = require('../package.json'); - -const packFile = `mongodb-client-encryption-${pkg.version}.tgz`; - -const REQUIRED_FILES = [ - 'package/binding.gyp', - 'package/CHANGELOG.md', - 'package/index.d.ts', - 'package/lib/index.js', - 'package/lib/autoEncrypter.js', - 'package/lib/buffer_pool.js', - 'package/lib/clientEncryption.js', - 'package/lib/common.js', - 'package/lib/providers/index.js', - 'package/lib/providers/gcp.js', - 'package/lib/providers/aws.js', - 'package/lib/providers/azure.js', - 'package/lib/providers/utils.js', - 'package/lib/cryptoCallbacks.js', - 'package/lib/errors.js', - 'package/lib/mongocryptdManager.js', - 'package/lib/stateMachine.js', - 'package/LICENSE', - 'package/package.json', - 'package/README.md', - 'package/src/mongocrypt.cc', - 'package/src/mongocrypt.h' -]; - -describe(`Release ${packFile}`, function () { - this.timeout(5000); - - let tarFileList; - before(() => { - expect(fs.existsSync(packFile)).to.equal(false); - cp.execSync('npm pack', { stdio: 'ignore' }); - tarFileList = []; - tar.list({ - file: packFile, - sync: true, - onentry(entry) { - tarFileList.push(entry.path); - } - }); - }); - - after(() => { - fs.unlinkSync(packFile); - }); - - for (const requiredFile of REQUIRED_FILES) { - it(`should contain ${requiredFile}`, () => { - expect(tarFileList).to.includes(requiredFile); - }); - } - - it('should not have extraneous files', () => { - const unexpectedFileList = tarFileList.filter(f => !REQUIRED_FILES.some(r => r === f)); - expect(unexpectedFileList).to.have.lengthOf(0, `Extra files: ${unexpectedFileList.join(', ')}`); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/requirements.helper.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/requirements.helper.js deleted file mode 100644 index 9dc5711..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/requirements.helper.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; - -// Data Key Stuff -const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID; -const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY; -const AWS_REGION = process.env.AWS_REGION; -const AWS_CMK_ID = process.env.AWS_CMK_ID; - -const awsKmsProviders = { - aws: { accessKeyId: AWS_ACCESS_KEY_ID, secretAccessKey: AWS_SECRET_ACCESS_KEY } -}; -const awsDataKeyOptions = { masterKey: { key: AWS_CMK_ID, region: AWS_REGION } }; - -const SKIP_LIVE_TESTS = !!process.env.MONGODB_NODE_SKIP_LIVE_TESTS; -const SKIP_AWS_TESTS = - SKIP_LIVE_TESTS || !AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY || !AWS_REGION || !AWS_CMK_ID; - -function isAWSCredentialProviderInstalled() { - try { - require.resolve('@aws-sdk/credential-providers'); - return true; - } catch { - return false; - } -} - -function isGCPCredentialProviderInstalled() { - try { - require.resolve('gcp-metadata'); - return true; - } catch { - return false; - } -} - -module.exports = { - SKIP_LIVE_TESTS, - SKIP_AWS_TESTS, - KEYS: { - AWS_ACCESS_KEY_ID, - AWS_SECRET_ACCESS_KEY, - AWS_REGION, - AWS_CMK_ID - }, - awsKmsProviders, - awsDataKeyOptions, - credentialProvidersInstalled: { - aws: isAWSCredentialProviderInstalled(), - gcp: isGCPCredentialProviderInstalled() - } -}; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/stateMachine.test.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/stateMachine.test.js deleted file mode 100644 index 31d96ba..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/stateMachine.test.js +++ /dev/null @@ -1,331 +0,0 @@ -'use strict'; - -const { EventEmitter, once } = require('events'); -const net = require('net'); -const tls = require('tls'); -const fs = require('fs'); -const { expect } = require('chai'); -const sinon = require('sinon'); -const mongodb = require('mongodb'); -const BSON = mongodb.BSON; -const StateMachine = require('../lib/stateMachine')({ mongodb }).StateMachine; - -describe('StateMachine', function () { - class MockRequest { - constructor(message, bytesNeeded) { - this._bytesNeeded = typeof bytesNeeded === 'number' ? bytesNeeded : 1024; - this._message = message; - this.endpoint = 'some.fake.host.com'; - this._kmsProvider = 'aws'; - } - - get message() { - return this._message; - } - - get bytesNeeded() { - return this._bytesNeeded; - } - - get kmsProvider() { - return this._kmsProvider; - } - - addResponse(buffer) { - this._bytesNeeded -= buffer.length; - } - } - - describe('#markCommand', function () { - let runCommandStub; - let dbStub; - let clientStub; - - beforeEach(function () { - this.sinon = sinon.createSandbox(); - runCommandStub = this.sinon.stub().resolves({}); - dbStub = this.sinon.createStubInstance(mongodb.Db, { - command: runCommandStub - }); - clientStub = this.sinon.createStubInstance(mongodb.MongoClient, { - db: dbStub - }); - }); - - const command = { - encryptedFields: {}, - a: new BSON.Long('0'), - b: new BSON.Int32(0) - }; - const options = { promoteLongs: false, promoteValues: false }; - const serializedCommand = BSON.serialize(command); - const stateMachine = new StateMachine({ bson: BSON }); - const callback = () => {}; - - context('when executing the command', function () { - it('does not promote values', function () { - stateMachine.markCommand(clientStub, 'test.coll', serializedCommand, callback); - expect(runCommandStub.calledWith(command, options)).to.be.true; - }); - }); - }); - - describe('kmsRequest', function () { - class MockSocket extends EventEmitter { - constructor(callback) { - super(); - this.on('connect', callback); - } - write() {} - destroy() {} - end(callback) { - Promise.resolve().then(callback); - } - } - - before(function () { - this.sinon = sinon.createSandbox(); - }); - - context('when handling standard kms requests', function () { - beforeEach(function () { - this.fakeSocket = undefined; - this.sinon.stub(tls, 'connect').callsFake((options, callback) => { - this.fakeSocket = new MockSocket(callback); - return this.fakeSocket; - }); - }); - - it('should only resolve once bytesNeeded drops to zero', function (done) { - const stateMachine = new StateMachine({ bson: BSON }); - const request = new MockRequest(Buffer.from('foobar'), 500); - let status = 'pending'; - stateMachine - .kmsRequest(request) - .then( - () => (status = 'resolved'), - () => (status = 'rejected') - ) - .catch(() => {}); - - this.fakeSocket.emit('connect'); - setTimeout(() => { - expect(status).to.equal('pending'); - expect(request.bytesNeeded).to.equal(500); - expect(request.kmsProvider).to.equal('aws'); - this.fakeSocket.emit('data', Buffer.alloc(300)); - setTimeout(() => { - expect(status).to.equal('pending'); - expect(request.bytesNeeded).to.equal(200); - this.fakeSocket.emit('data', Buffer.alloc(200)); - setTimeout(() => { - expect(status).to.equal('resolved'); - expect(request.bytesNeeded).to.equal(0); - done(); - }); - }); - }); - }); - }); - - context('when tls options are provided', function () { - context('when the options are insecure', function () { - [ - 'tlsInsecure', - 'tlsAllowInvalidCertificates', - 'tlsAllowInvalidHostnames', - 'tlsDisableOCSPEndpointCheck', - 'tlsDisableCertificateRevocationCheck' - ].forEach(function (option) { - context(`when the option is ${option}`, function () { - const stateMachine = new StateMachine({ - bson: BSON, - tlsOptions: { aws: { [option]: true } } - }); - const request = new MockRequest(Buffer.from('foobar'), 500); - - it('rejects with the validation error', function (done) { - stateMachine.kmsRequest(request).catch(err => { - expect(err.message).to.equal(`Insecure TLS options prohibited for aws: ${option}`); - done(); - }); - }); - }); - }); - }); - - context('when the options are secure', function () { - context('when providing tlsCertificateKeyFile', function () { - const stateMachine = new StateMachine({ - bson: BSON, - tlsOptions: { aws: { tlsCertificateKeyFile: 'test.pem' } } - }); - const request = new MockRequest(Buffer.from('foobar'), -1); - const buffer = Buffer.from('foobar'); - let connectOptions; - - it('sets the cert and key options in the tls connect options', function (done) { - this.sinon.stub(fs, 'readFileSync').callsFake(fileName => { - expect(fileName).to.equal('test.pem'); - return buffer; - }); - this.sinon.stub(tls, 'connect').callsFake((options, callback) => { - connectOptions = options; - this.fakeSocket = new MockSocket(callback); - return this.fakeSocket; - }); - stateMachine.kmsRequest(request).then(function () { - expect(connectOptions.cert).to.equal(buffer); - expect(connectOptions.key).to.equal(buffer); - done(); - }); - this.fakeSocket.emit('data', Buffer.alloc(0)); - }); - }); - - context('when providing tlsCAFile', function () { - const stateMachine = new StateMachine({ - bson: BSON, - tlsOptions: { aws: { tlsCAFile: 'test.pem' } } - }); - const request = new MockRequest(Buffer.from('foobar'), -1); - const buffer = Buffer.from('foobar'); - let connectOptions; - - it('sets the ca options in the tls connect options', function (done) { - this.sinon.stub(fs, 'readFileSync').callsFake(fileName => { - expect(fileName).to.equal('test.pem'); - return buffer; - }); - this.sinon.stub(tls, 'connect').callsFake((options, callback) => { - connectOptions = options; - this.fakeSocket = new MockSocket(callback); - return this.fakeSocket; - }); - stateMachine.kmsRequest(request).then(function () { - expect(connectOptions.ca).to.equal(buffer); - done(); - }); - this.fakeSocket.emit('data', Buffer.alloc(0)); - }); - }); - - context('when providing tlsCertificateKeyFilePassword', function () { - const stateMachine = new StateMachine({ - bson: BSON, - tlsOptions: { aws: { tlsCertificateKeyFilePassword: 'test' } } - }); - const request = new MockRequest(Buffer.from('foobar'), -1); - let connectOptions; - - it('sets the passphrase option in the tls connect options', function (done) { - this.sinon.stub(tls, 'connect').callsFake((options, callback) => { - connectOptions = options; - this.fakeSocket = new MockSocket(callback); - return this.fakeSocket; - }); - stateMachine.kmsRequest(request).then(function () { - expect(connectOptions.passphrase).to.equal('test'); - done(); - }); - this.fakeSocket.emit('data', Buffer.alloc(0)); - }); - }); - }); - }); - - afterEach(function () { - this.sinon.restore(); - }); - }); - - describe('Socks5 support', function () { - let socks5srv; - let hasTlsConnection; - let withUsernamePassword; - - beforeEach(async () => { - hasTlsConnection = false; - socks5srv = net.createServer(async socket => { - if (withUsernamePassword) { - expect(await once(socket, 'data')).to.deep.equal([Buffer.from('05020002', 'hex')]); - socket.write(Buffer.from('0502', 'hex')); - expect(await once(socket, 'data')).to.deep.equal([ - Buffer.concat([ - Buffer.from('0103', 'hex'), - Buffer.from('foo'), - Buffer.from('03', 'hex'), - Buffer.from('bar') - ]) - ]); - socket.write(Buffer.from('0100', 'hex')); - } else { - expect(await once(socket, 'data')).to.deep.equal([Buffer.from('050100', 'hex')]); - socket.write(Buffer.from('0500', 'hex')); - } - expect(await once(socket, 'data')).to.deep.equal([ - Buffer.concat([ - Buffer.from('0501000312', 'hex'), - Buffer.from('some.fake.host.com'), - Buffer.from('01bb', 'hex') - ]) - ]); - socket.write(Buffer.from('0500007f0000010100', 'hex')); - expect((await once(socket, 'data'))[0][1]).to.equal(3); // TLS handshake version byte - hasTlsConnection = true; - socket.end(); - }); - socks5srv.listen(0); - await once(socks5srv, 'listening'); - }); - - afterEach(() => { - socks5srv.close(); - }); - - it('should create HTTPS connections through a Socks5 proxy (no proxy auth)', async function () { - const stateMachine = new StateMachine({ - bson: BSON, - proxyOptions: { - proxyHost: 'localhost', - proxyPort: socks5srv.address().port - } - }); - - const request = new MockRequest(Buffer.from('foobar'), 500); - try { - await stateMachine.kmsRequest(request); - } catch (err) { - expect(err.name).to.equal('MongoCryptError'); - expect(err.originalError.code).to.equal('ECONNRESET'); - expect(hasTlsConnection).to.equal(true); - return; - } - expect.fail('missed exception'); - }); - - it('should create HTTPS connections through a Socks5 proxy (username/password auth)', async function () { - withUsernamePassword = true; - const stateMachine = new StateMachine({ - bson: BSON, - proxyOptions: { - proxyHost: 'localhost', - proxyPort: socks5srv.address().port, - proxyUsername: 'foo', - proxyPassword: 'bar' - } - }); - - const request = new MockRequest(Buffer.from('foobar'), 500); - try { - await stateMachine.kmsRequest(request); - } catch (err) { - expect(err.name).to.equal('MongoCryptError'); - expect(err.originalError.code).to.equal('ECONNRESET'); - expect(hasTlsConnection).to.equal(true); - return; - } - expect.fail('missed exception'); - }); - }); -}); diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/tools/chai-addons.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/tools/chai-addons.js deleted file mode 100644 index 68dd475..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/tools/chai-addons.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -// configure chai -const chai = require('chai'); -chai.use(require('sinon-chai')); -chai.use(require('chai-subset')); - -chai.config.truncateThreshold = 0; diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/tools/mongodb_reporter.js b/ext/libmongocrypt/libmongocrypt/bindings/node/test/tools/mongodb_reporter.js deleted file mode 100644 index 9e8461c..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/tools/mongodb_reporter.js +++ /dev/null @@ -1,325 +0,0 @@ -//@ts-check -'use strict'; -const mocha = require('mocha'); -const chalk = require('chalk'); - -chalk.level = 3; - -const { - EVENT_RUN_BEGIN, - EVENT_RUN_END, - EVENT_TEST_FAIL, - EVENT_TEST_PASS, - EVENT_SUITE_BEGIN, - EVENT_SUITE_END, - EVENT_TEST_PENDING, - EVENT_TEST_BEGIN, - EVENT_TEST_END -} = mocha.Runner.constants; - -const fs = require('fs'); -const os = require('os'); - -/** - * @typedef {object} MongoMochaSuiteExtension - * @property {Date} timestamp - suite start date - * @property {string} stdout - capture of stdout - * @property {string} stderr - capture of stderr - * @property {MongoMochaTest} test - capture of stderr - * @typedef {object} MongoMochaTestExtension - * @property {Date} startTime - test start date - * @property {Date} endTime - test end date - * @property {number} elapsedTime - difference between end and start - * @property {Error} [error] - The possible error from a test - * @property {true} [skipped] - Set if test was skipped - * @typedef {MongoMochaSuiteExtension & Mocha.Suite} MongoMochaSuite - * @typedef {MongoMochaTestExtension & Mocha.Test} MongoMochaTest - */ - -// Turn this on if you have to debug this custom reporter! -let REPORT_TO_STDIO = false; - -function captureStream(stream) { - var oldWrite = stream.write; - var buf = ''; - stream.write = function (chunk) { - buf += chunk.toString(); // chunk is a String or Buffer - oldWrite.apply(stream, arguments); - }; - - return { - unhook: function unhook() { - stream.write = oldWrite; - return buf; - }, - captured: function () { - return buf; - } - }; -} - -/** - * @param {Mocha.Runner} runner - * @this {any} - */ -class MongoDBMochaReporter extends mocha.reporters.Spec { - constructor(runner) { - super(runner); - /** @type {Map} */ - this.suites = new Map(); - this.xunitWritten = false; - runner.on(EVENT_RUN_BEGIN, () => this.start()); - runner.on(EVENT_RUN_END, () => this.end()); - runner.on(EVENT_SUITE_BEGIN, suite => this.onSuite(suite)); - runner.on(EVENT_TEST_BEGIN, test => this.onTest(test)); - runner.on(EVENT_TEST_PASS, test => this.pass(test)); - runner.on(EVENT_TEST_FAIL, (test, error) => this.fail(test, error)); - runner.on(EVENT_TEST_PENDING, test => this.pending(test)); - runner.on(EVENT_SUITE_END, suite => this.suiteEnd(suite)); - runner.on(EVENT_TEST_END, test => this.testEnd(test)); - - process.on('SIGINT', () => this.end(true)); - } - start() {} - - end(ctrlC) { - try { - if (ctrlC) console.log('emergency exit!'); - const output = { testSuites: [] }; - - for (const [id, [className, { suite }]] of [...this.suites.entries()].entries()) { - let totalSuiteTime = 0; - let testCases = []; - let failureCount = 0; - - const tests = /** @type {MongoMochaTest[]}*/ (suite.tests); - for (const test of tests) { - let time = test.elapsedTime / 1000; - time = Number.isNaN(time) ? 0 : time; - - totalSuiteTime += time; - failureCount += test.state === 'failed' ? 1 : 0; - - /** @type {string | Date | number} */ - let startTime = test.startTime; - startTime = startTime ? startTime.toISOString() : 0; - - /** @type {string | Date | number} */ - let endTime = test.endTime; - endTime = endTime ? endTime.toISOString() : 0; - - let error = test.error; - let failure = error - ? { - type: error.constructor.name, - message: error.message, - stack: error.stack - } - : undefined; - - let skipped = !!test.skipped; - - testCases.push({ - name: test.title, - className, - time, - startTime, - endTime, - skipped, - failure - }); - } - - /** @type {string | Date | number} */ - let timestamp = suite.timestamp; - timestamp = timestamp ? timestamp.toISOString().split('.')[0] : ''; - - output.testSuites.push({ - package: suite.file.includes('integration') ? 'Integration' : 'Unit', - id, - name: className, - timestamp, - hostname: os.hostname(), - tests: suite.tests.length, - failures: failureCount, - errors: '0', - time: totalSuiteTime, - testCases, - stdout: suite.stdout, - stderr: suite.stderr - }); - } - - if (!this.xunitWritten) { - fs.writeFileSync('xunit.xml', outputToXML(output), { encoding: 'utf8' }); - } - this.xunitWritten = true; - console.log(chalk.bold('wrote xunit.xml')); - } catch (error) { - console.error(chalk.red(`Failed to output xunit report! ${error}`)); - } finally { - if (ctrlC) process.exit(1); - } - } - - /** - * @param {MongoMochaSuite} suite - */ - onSuite(suite) { - if (suite.root) return; - if (!this.suites.has(suite.fullTitle())) { - suite.timestamp = new Date(); - this.suites.set(suite.fullTitle(), { - suite, - stdout: captureStream(process.stdout), - stderr: captureStream(process.stderr) - }); - } else { - console.warn(`${chalk.yellow('WARNING:')} ${suite.fullTitle()} started twice`); - } - } - - /** - * @param {MongoMochaSuite} suite - */ - suiteEnd(suite) { - if (suite.root) return; - const currentSuite = this.suites.get(suite.fullTitle()); - if (!currentSuite) { - console.error('Suite never started >:('); - process.exit(1); - } - if (currentSuite.stdout || currentSuite.stderr) { - suite.stdout = currentSuite.stdout.unhook(); - suite.stderr = currentSuite.stderr.unhook(); - delete currentSuite.stdout; - delete currentSuite.stderr; - } - } - - /** - * @param {MongoMochaTest} test - */ - onTest(test) { - test.startTime = new Date(); - } - - /** - * @param {MongoMochaTest} test - */ - testEnd(test) { - test.endTime = new Date(); - test.elapsedTime = Number(test.endTime) - Number(test.startTime); - } - - /** - * @param {MongoMochaTest} test - */ - pass(test) { - if (REPORT_TO_STDIO) console.log(chalk.green(`✔ ${test.fullTitle()}`)); - } - - /** - * @param {MongoMochaTest} test - * @param {Error} error - */ - fail(test, error) { - if (REPORT_TO_STDIO) console.log(chalk.red(`⨯ ${test.fullTitle()} -- ${error.message}`)); - test.error = error; - } - - /** - * @param {MongoMochaTest & {skipReason?: string}} test - */ - pending(test) { - if (REPORT_TO_STDIO) console.log(chalk.cyan(`↬ ${test.fullTitle()}`)); - if (typeof test.skipReason === 'string') { - console.log(chalk.cyan(`${' '.repeat(test.titlePath().length + 1)}↬ ${test.skipReason}`)); - } - test.skipped = true; - } -} - -module.exports = MongoDBMochaReporter; - -function replaceIllegalXMLCharacters(string) { - // prettier-ignore - return String(string) - .split('"').join('"') - .split('<').join('﹤') - .split('>').join('﹥') - .split('&').join('﹠'); -} - -const ANSI_ESCAPE_REGEX = - // eslint-disable-next-line no-control-regex - /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; -function outputToXML(output) { - function cdata(str) { - return `') - .join('\\]\\]\\>')}]]>`; - } - - function makeTag(name, attributes, selfClose, content) { - const attributesString = Object.entries(attributes || {}) - .map(([k, v]) => `${k}="${replaceIllegalXMLCharacters(v)}"`) - .join(' '); - let tag = `<${name}${attributesString ? ' ' + attributesString : ''}`; - if (selfClose) return tag + '/>\n'; - else tag += '>'; - if (content) return tag + content + ``; - return tag; - } - - let s = - '\n\n\n'; - - for (const suite of output.testSuites) { - s += makeTag('testsuite', { - package: suite.package, - id: suite.id, - name: suite.name, - timestamp: suite.timestamp, - hostname: suite.hostname, - tests: suite.tests, - failures: suite.failures, - errors: suite.errors, - time: suite.time - }); - s += '\n\t' + makeTag('properties') + '\n'; // can put metadata here? - for (const test of suite.testCases) { - s += - '\t' + - makeTag( - 'testcase', - { - name: test.name, - classname: test.className, - time: test.time, - start: test.startTime, - end: test.endTime - }, - !test.failure && !test.skipped - ); - if (test.failure) { - s += - '\n\t\t' + - makeTag('failure', { type: test.failure.type }, false, cdata(test.failure.stack)) + - '\n'; - s += `\t\n`; - } - if (test.skipped) { - s += makeTag('skipped', {}, true); - s += `\t\n`; - } - } - s += '\t' + makeTag('system-out', {}, false, cdata(suite.stdout)) + '\n'; - s += '\t' + makeTag('system-err', {}, false, cdata(suite.stderr)) + '\n'; - s += `\n`; - } - - return s + '\n'; -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/types/index.test-d.ts b/ext/libmongocrypt/libmongocrypt/bindings/node/test/types/index.test-d.ts deleted file mode 100644 index ae0b6b9..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/node/test/types/index.test-d.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { expectAssignable, expectError, expectType, expectNotType, expectNotAssignable } from 'tsd'; -import { RangeOptions, AWSEncryptionKeyOptions, AzureEncryptionKeyOptions, ClientEncryption, GCPEncryptionKeyOptions, ClientEncryptionEncryptOptions, KMSProviders } from '../..'; - -type RequiredCreateEncryptedCollectionSettings = Parameters< - ClientEncryption['createEncryptedCollection'] ->[2]; - -expectError({}); -expectError({ - provider: 'blah!', - createCollectionOptions: { encryptedFields: {} } -}); -expectError({ - provider: 'aws', - createCollectionOptions: {} -}); -expectError({ - provider: 'aws', - createCollectionOptions: { encryptedFields: null } -}); - -expectAssignable({ - provider: 'aws', - createCollectionOptions: { encryptedFields: {} } -}); -expectAssignable({ - provider: 'aws', - createCollectionOptions: { encryptedFields: {} }, - masterKey: { } as AWSEncryptionKeyOptions | AzureEncryptionKeyOptions | GCPEncryptionKeyOptions -}); - -{ - // NODE-5041 - incorrect spelling of rangeOpts in typescript definitions - const options = {} as ClientEncryptionEncryptOptions; - expectType(options.rangeOptions) -} - -{ - // KMSProviders - // aws - expectAssignable({ accessKeyId: '', secretAccessKey: '' }); - expectAssignable({ accessKeyId: '', secretAccessKey: '', sessionToken: undefined }); - expectAssignable({ accessKeyId: '', secretAccessKey: '', sessionToken: '' }); - // automatic - expectAssignable({}); - - // azure - expectAssignable({ tenantId: 'a', clientId: 'a', clientSecret: 'a' }); - expectAssignable({ tenantId: 'a', clientId: 'a', clientSecret: 'a' }); - expectAssignable({ tenantId: 'a', clientId: 'a', clientSecret: 'a', identityPlatformEndpoint: undefined }); - expectAssignable({ tenantId: 'a', clientId: 'a', clientSecret: 'a', identityPlatformEndpoint: '' }); - expectAssignable({ accessToken: 'a' }); - expectAssignable({}); - - // gcp - expectAssignable({ email: 'a', privateKey: 'a' }); - expectAssignable({ email: 'a', privateKey: 'a', endpoint: undefined }); - expectAssignable({ email: 'a', privateKey: 'a', endpoint: 'a' }); - expectAssignable({ accessToken: 'a' }); - // automatic - expectAssignable({}); - -} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-setup.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-setup.sh new file mode 100755 index 0000000..60fa5e5 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-setup.sh @@ -0,0 +1,43 @@ +#!/usr/bin/bash + +set -eux + +DRIVERS_TOOLS="$(pwd)/drivers-tools" +PROJECT_DIRECTORY="${project_directory}" +PYMONGO_DIR="$(pwd)/mongo-python-driver" + +# Python has cygwin path problems on Windows. +if [ "Windows_NT" = "${OS:-}" ]; then + DRIVERS_TOOLS=$(cygpath -m $DRIVERS_TOOLS) + PROJECT_DIRECTORY=$(cygpath -m $PROJECT_DIRECTORY) +fi +export PROJECT_DIRECTORY +export DRIVERS_TOOLS + +export MONGO_ORCHESTRATION_HOME="$DRIVERS_TOOLS/.evergreen/orchestration" +export MONGODB_BINARIES="$DRIVERS_TOOLS/mongodb/bin" +export MONGOCRYPT_DIR=${PROJECT_DIRECTORY}/all/${variant_name} + +cat < expansion.yml +DRIVERS_TOOLS: "$DRIVERS_TOOLS" +MONGO_ORCHESTRATION_HOME: "$MONGO_ORCHESTRATION_HOME" +MONGODB_BINARIES: "$MONGODB_BINARIES" +PROJECT_DIRECTORY: "$PROJECT_DIRECTORY" +PYMONGO_DIR: "$PYMONGO_DIR" +MONGOCRYPT_DIR: "$MONGOCRYPT_DIR" +EOT + +# Set up drivers-tools with a .env file. +git clone https://github.com/mongodb-labs/drivers-evergreen-tools.git ${DRIVERS_TOOLS} +cat < ${DRIVERS_TOOLS}/.env +DRIVERS_TOOLS="$DRIVERS_TOOLS" +MONGO_ORCHESTRATION_HOME="$MONGO_ORCHESTRATION_HOME" +MONGODB_BINARIES="$MONGODB_BINARIES" +PROJECT_DIRECTORY="$PROJECT_DIRECTORY" +EOT + +# Get the secrets +bash $DRIVERS_TOOLS/.evergreen/csfle/setup-secrets.sh + +# Clone mongo-python-driver +git clone https://github.com/mongodb/mongo-python-driver.git ${PYMONGO_DIR} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-teardown.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-teardown.sh new file mode 100755 index 0000000..143e573 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-teardown.sh @@ -0,0 +1,6 @@ +#! /bin/bash +set -o xtrace # Write all commands first to stderr +set -o errexit # Exit the script with error if any of the commands fail + +bash ${DRIVERS_TOOLS}/.evergreen/csfle/teardown.sh +bash ${DRIVERS_TOOLS}/.evergreen/teardown.sh diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-test.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-test.sh new file mode 100755 index 0000000..8bf1eb1 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/integ-test.sh @@ -0,0 +1,50 @@ +#! /bin/bash +set -eux + +pushd $(pwd)/libmongocrypt/bindings/python + +# For createvirtualenv and find_python3 +. .evergreen/utils.sh + +BASE_PYTHON=$(find_python3) + +# MONGOCRYPT_DIR is set by libmongocrypt/.evergreen/config.yml +MONGOCRYPT_DIR="$MONGOCRYPT_DIR" + +MACHINE=$(uname -m) +if [ $MACHINE == "aarch64" ]; then + PYTHON="/opt/mongodbtoolchain/v4/bin/python3" + TARGET=rhel82 +else + TARGET=rhel80 + PYTHON="/opt/python/3.8/bin/python3" +fi + +CRYPT_SHARED_DIR="$(pwd)/crypt_shared" +/opt/mongodbtoolchain/v3/bin/python3 $DRIVERS_TOOLS/.evergreen/mongodl.py --component \ + crypt_shared --version latest --out $CRYPT_SHARED_DIR --target $TARGET + +if [ -e "${MONGOCRYPT_DIR}/lib64/" ]; then + export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib64/libmongocrypt.so + PYMONGOCRYPT_LIB_CRYPTO=${MONGOCRYPT_DIR}/lib64/libmongocrypt.so +else + export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib/libmongocrypt.so + PYMONGOCRYPT_LIB_CRYPTO=${MONGOCRYPT_DIR}/lib/libmongocrypt.so +fi + +createvirtualenv $PYTHON .venv +pip install -e . +pushd $PYMONGO_DIR +pip install -e ".[test,encryption]" +source ${DRIVERS_TOOLS}/.evergreen/csfle/secrets-export.sh +set -x +TEST_CRYPT_SHARED=1 DYLD_FALLBACK_LIBRARY_PATH=$CRYPT_SHARED_DIR/lib/:${DYLD_FALLBACK_LIBRARY_PATH:-} \ + LD_LIBRARY_PATH=$CRYPT_SHARED_DIR/lib:${LD_LIBRARY_PATH-} \ + PATH=$CRYPT_SHARED_DIR/bin:$PATH \ + AUTH=auth SSL=ssl \ + .evergreen/run-tests.sh -m encryption + +popd +deactivate +rm -rf .venv +popd diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/test.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/test.sh index a528535..cc7e52f 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/test.sh +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/test.sh @@ -5,62 +5,93 @@ set -o xtrace # Write all commands first to stderr set -o errexit # Exit the script with error if any of the commands fail -# For createvirtualenv. +# For createvirtualenv and find_python3 . .evergreen/utils.sh +BASE_PYTHON=$(find_python3) + # MONGOCRYPT_DIR is set by libmongocrypt/.evergreen/config.yml MONGOCRYPT_DIR="$MONGOCRYPT_DIR" git clone https://github.com/mongodb-labs/drivers-evergreen-tools.git if [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/bin/mongocrypt.dll + PYMONGOCRYPT_LIB_CRYPTO=$(cygpath -m ${MONGOCRYPT_DIR}/bin/mongocrypt.dll) export PYMONGOCRYPT_LIB=$(cygpath -m $PYMONGOCRYPT_LIB) - PYTHONS=("C:/python/Python37/python.exe" - "C:/python/Python38/python.exe" + PYTHONS=("C:/python/Python38/python.exe" "C:/python/Python39/python.exe" "C:/python/Python310/python.exe" - "C:/python/Python311/python.exe") + "C:/python/Python311/python.exe" + "C:/python/Python312/python.exe") export CRYPT_SHARED_PATH=../crypt_shared/bin/mongo_crypt_v1.dll C:/python/Python310/python.exe drivers-evergreen-tools/.evergreen/mongodl.py --component crypt_shared \ --version latest --out ../crypt_shared/ elif [ "Darwin" = "$(uname -s)" ]; then export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib/libmongocrypt.dylib - if [[ $(uname -m) == 'arm64' ]]; then - PYTHONS=("/Library/Frameworks/Python.framework/Versions/3.10/bin/python3" - ) - else - PYTHONS=("python3" # Python 3 from brew - "/Library/Frameworks/Python.framework/Versions/3.7/bin/python3" - "/Library/Frameworks/Python.framework/Versions/3.8/bin/python3" - "/Library/Frameworks/Python.framework/Versions/3.9/bin/python3" - "/Library/Frameworks/Python.framework/Versions/3.10/bin/python3" - "/Library/Frameworks/Python.framework/Versions/3.11/bin/python3") - fi + PYMONGOCRYPT_LIB_CRYPTO=${MONGOCRYPT_DIR}/lib/libmongocrypt.dylib + PYTHONS=( + "/Library/Frameworks/Python.framework/Versions/3.9/bin/python3" + "/Library/Frameworks/Python.framework/Versions/3.10/bin/python3" + "/Library/Frameworks/Python.framework/Versions/3.11/bin/python3" + "/Library/Frameworks/Python.framework/Versions/3.12/bin/python3" + ) export CRYPT_SHARED_PATH="../crypt_shared/lib/mongo_crypt_v1.dylib" python3 drivers-evergreen-tools/.evergreen/mongodl.py --component crypt_shared \ --version latest --out ../crypt_shared/ else - export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib64/libmongocrypt.so - PYTHONS=("/opt/mongodbtoolchain/v3/bin/python3" - ) + if [ -e "${MONGOCRYPT_DIR}/lib64/" ]; then + export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib64/libmongocrypt.so + PYMONGOCRYPT_LIB_CRYPTO=${MONGOCRYPT_DIR}/lib64/libmongocrypt.so + else + export PYMONGOCRYPT_LIB=${MONGOCRYPT_DIR}/nocrypto/lib/libmongocrypt.so + PYMONGOCRYPT_LIB_CRYPTO=${MONGOCRYPT_DIR}/lib/libmongocrypt.so + fi + export CRYPT_SHARED_PATH="../crypt_shared/lib/mongo_crypt_v1.so" + MACHINE=$(uname -m) + if [ $MACHINE == "aarch64" ]; then + TARGET=rhel82 + PYTHONS=("/opt/mongodbtoolchain/v3/bin/python3" + "/opt/mongodbtoolchain/v4/bin/python3" + ) + else + TARGET=rhel80 + PYTHONS=("/opt/python/3.8/bin/python3" + "/opt/python/3.9/bin/python3" + "/opt/python/3.10/bin/python3" + "/opt/python/3.11/bin/python3" + "/opt/python/3.12/bin/python3" + ) + fi /opt/mongodbtoolchain/v3/bin/python3 drivers-evergreen-tools/.evergreen/mongodl.py --component \ - crypt_shared --version latest --out ../crypt_shared/ --target rhel70 + crypt_shared --version latest --out ../crypt_shared/ --target $TARGET fi - for PYTHON_BINARY in "${PYTHONS[@]}"; do echo "Running test with python: $PYTHON_BINARY" $PYTHON_BINARY -c 'import sys; print(sys.version)' + git clean -dffx createvirtualenv $PYTHON_BINARY .venv - python -m pip install --prefer-binary -r test-requirements.txt - python setup.py test - echo "Running tests with CSFLE on dynamic library path..." + python -m pip install --prefer-binary -v -e ".[test]" + echo "Running tests with crypto enabled libmongocrypt..." + PYMONGOCRYPT_LIB=$PYMONGOCRYPT_LIB_CRYPTO python -c 'from pymongocrypt.binding import lib;assert lib.mongocrypt_is_crypto_available(), "mongocrypt_is_crypto_available() returned False"' + PYMONGOCRYPT_LIB=$PYMONGOCRYPT_LIB_CRYPTO python -m pytest -v --ignore=test/performance . + echo "Running tests with crypt_shared on dynamic library path..." TEST_CRYPT_SHARED=1 DYLD_FALLBACK_LIBRARY_PATH=../crypt_shared/lib/:$DYLD_FALLBACK_LIBRARY_PATH \ LD_LIBRARY_PATH=../crypt_shared/lib:$LD_LIBRARY_PATH \ PATH=../crypt_shared/bin:$PATH \ - python setup.py test + python -m pytest -v --ignore=test/performance . deactivate rm -rf .venv done + +# Verify the sbom file +LIBMONGOCRYPT_VERSION=$(cat ./libmongocrypt-version.txt) +EXPECTED="pkg:github/mongodb/libmongocrypt@$LIBMONGOCRYPT_VERSION" +if grep -q $EXPECTED sbom.json; then + echo "SBOM is up to date!" +else + echo "SBOM is out of date! Run the \"update-sbom.sh\" script." + exit 1 +fi diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/utils.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/utils.sh index 8f85935..57055fb 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/utils.sh +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/.evergreen/utils.sh @@ -7,24 +7,78 @@ createvirtualenv () { PYTHON=$1 VENVPATH=$2 - if $PYTHON -m virtualenv --version; then - VIRTUALENV="$PYTHON -m virtualenv --system-site-packages --never-download" - elif $PYTHON -m venv -h>/dev/null; then - VIRTUALENV="$PYTHON -m venv --system-site-packages" - elif command -v virtualenv; then - VIRTUALENV="$(command -v virtualenv) -p $PYTHON --system-site-packages --never-download" + # Prefer venv + VENV="$PYTHON -m venv" + if [ "$(uname -s)" = "Darwin" ]; then + VIRTUALENV="$PYTHON -m virtualenv" else - echo "Cannot test without virtualenv" - exit 1 + VIRTUALENV=$(command -v virtualenv 2>/dev/null || echo "$PYTHON -m virtualenv") + VIRTUALENV="$VIRTUALENV -p $PYTHON" + fi + if ! $VENV $VENVPATH 2>/dev/null; then + # Workaround for bug in older versions of virtualenv. + $VIRTUALENV $VENVPATH 2>/dev/null || $VIRTUALENV $VENVPATH fi - $VIRTUALENV $VENVPATH - if [ "Windows_NT" = "$OS" ]; then + if [ "Windows_NT" = "${OS:-}" ]; then + # Workaround https://bugs.python.org/issue32451: + # mongovenv/Scripts/activate: line 3: $'\r': command not found + dos2unix $VENVPATH/Scripts/activate || true . $VENVPATH/Scripts/activate else . $VENVPATH/bin/activate fi - # Upgrade to the latest versions of pip setuptools wheel so that - # pip can always download the latest cryptography+cffi wheels. + + export PIP_QUIET=1 python -m pip install --upgrade pip - python -m pip install --upgrade pip setuptools wheel +} + +# Usage: +# PYTHON = find_python3 +find_python3() { + PYTHON="" + # Add a fallback system python3 if it is available and Python 3.8+. + if is_python_38 "$(command -v python3)"; then + PYTHON="$(command -v python3)" + fi + # Find a suitable toolchain version, if available. + if [ "$(uname -s)" = "Darwin" ]; then + # macos 11.00 + if [ -d "/Library/Frameworks/Python.Framework/Versions/3.10" ]; then + PYTHON="/Library/Frameworks/Python.Framework/Versions/3.10/bin/python3" + # macos 10.14 + elif [ -d "/Library/Frameworks/Python.Framework/Versions/3.8" ]; then + PYTHON="/Library/Frameworks/Python.Framework/Versions/3.8/bin/python3" + fi + elif [ "Windows_NT" = "${OS:-}" ]; then # Magic variable in cygwin + PYTHON="C:/python/Python38/python.exe" + else + # Prefer our own toolchain, fall back to mongodb toolchain if it has Python 3.8+. + if [ -f "/opt/python/3.8/bin/python3" ]; then + PYTHON="/opt/python/3.8/bin/python3" + elif is_python_38 "$(command -v /opt/mongodbtoolchain/v4/bin/python3)"; then + PYTHON="/opt/mongodbtoolchain/v4/bin/python3" + elif is_python_38 "$(command -v /opt/mongodbtoolchain/v3/bin/python3)"; then + PYTHON="/opt/mongodbtoolchain/v3/bin/python3" + fi + fi + if [ -z "$PYTHON" ]; then + echo "Cannot run pre-commit without python3.8+ installed!" + exit 1 + fi + echo "$PYTHON" +} + +# Function that returns success if the provided Python binary is version 3.8 or later +# Usage: +# is_python_38 /path/to/python +# * param1: Python binary +is_python_38() { + if [ -z "$1" ]; then + return 1 + elif $1 -c "import sys; exit(sys.version_info[:2] < (3, 8))"; then + # runs when sys.version_info[:2] >= (3, 8) + return 0 + else + return 1 + fi } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst b/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst index 9aabffa..05b93a3 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst @@ -1,10 +1,70 @@ Changelog ========= +Changes in Version 1.10.1 +------------------------ + +- Bundle libmongocrypt 1.10.1 in release wheels. + +Changes in Version 1.10.0 +------------------------ + +- Add Python async support. +- Drop support for Python 3.7 and PyPy 3.8. Python >=3.8 or PyPy >=3.9 is now required. +- Add support for range-based Queryable Encryption with the new "range" + algorithm on MongoDB 8.0+. This replaces the experimental "rangePreview" algorithm. +- Add Secure Software Development Life Cycle automation to release process. + GitHub Releases for pymongocrypt now include a Software Bill of Materials, and signature + files corresponding to the distribution files released on PyPI. + +Changes in Version 1.9.2 +------------------------ + +- Fix support for building source distributions with setuptools >= 70. + + +Changes in Version 1.9.1 +------------------------ + +- Fix bug in our release process which blocked uploading 1.9.0. + +Changes in Version 1.9.0 +------------------------ + +- Add support for named KMS providers like "local:name1". + This feature requires libmongocrypt >= 1.9.0. +- Use libmongocrypt native crypto when available which results in 10-50x better performance. + On Linux, it is recommended to download the platform specific build and + set PYMONGOCRYPT_LIB to the crypto-enabled libmongocrypt.so. +- Bundle the crypto-enabled libmongocrypt builds in macOS and Windows wheels for better performance. +- Bundle libmongocrypt 1.9.0 in release wheels. + +Changes in Version 1.8.0 +------------------------ + +- Update from manylinux2010 to manylinux2014 wheels. +- Bundle libmongocrypt 1.8.4 in release wheels. +- Add support for manylinux_2_28_aarch64 wheels. + +Changes in Version 1.7.0 +------------------------ + +- Add support for Python 3.12 on MacOS and Linux. +- Update required cryptography version to >=2.5. + +Changes in Version 1.6.1 +------------------------ + +- Bundle libmongocrypt 1.8.1 in release wheels. + Changes in Version 1.6.0 ------------------------ - Drop support for Python 2 and Python <3.7. Python >=3.7 is now required. +- Bundle libmongocrypt 1.8.0 in release wheels. +- **Remove support for libmongocrypt <=1.8.0, libmongocrypt >=1.8.0 + is now required.** Note this is only relevant for users that install from + source or use the ``PYMONGOCRYPT_LIB`` environment variable. Changes in Version 1.5.2 ------------------------ diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/README.rst b/ext/libmongocrypt/libmongocrypt/bindings/python/README.rst index 454f9e5..823bfdd 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/README.rst +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/README.rst @@ -13,7 +13,7 @@ Python wrapper library for libmongocrypt that supports client side encryption in drivers. PyMongoCrypt uses `cffi `_ and `cryptography `_. -PyMongoCrypt supports Python 3.7+ and PyPy3.7+. +PyMongoCrypt supports Python 3.8+ and PyPy3.9+. Support / Feedback ================== @@ -77,7 +77,7 @@ PyMongoCrypt can be installed with `pip `_:: $ python -m pip install pymongocrypt $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" - 1.2.1 + 1.9.0 PyMongoCrypt ships wheels for macOS, Windows, and manylinux2010 that include @@ -102,7 +102,10 @@ First, install PyMongoCrypt from source:: $ git clone git@github.com:mongodb/libmongocrypt.git $ python -m pip install ./libmongocrypt/bindings/python -Next, install libmongocrypt. +Next, install libmongocrypt: + +Installing libmongocrypt +^^^^^^^^^^^^^^^^^^^^^^^^ libmongocrypt is continuously built and published on evergreen. The latest tarball containing libmongocrypt built on all supported variants is @@ -114,38 +117,56 @@ For example:: $ curl -O https://s3.amazonaws.com/mciuploads/libmongocrypt/all/master/latest/libmongocrypt-all.tar.gz $ mkdir libmongocrypt-all && tar xzf libmongocrypt-all.tar.gz -C libmongocrypt-all $ ls libmongocrypt-all - amazon2 rhel-62-64-bit rhel72-zseries-test ubuntu1604-arm64 - debian10 rhel-67-s390x suse12-64 ubuntu1804-64 - debian92 rhel-70-64-bit suse12-s390x ubuntu1804-arm64 - linux-64-amazon-ami rhel-71-ppc64el suse15-64 windows-test - macos rhel-80-64-bit ubuntu1604 + amazon2 debian92 rhel-80-64-bit rhel72-zseries-test ubuntu1804-arm64 + amazon2-arm64 linux-64-amazon-ami rhel-81-ppc64el suse12-64 ubuntu2004-64 + amazon2023 macos rhel-82-arm64 suse15-64 ubuntu2004-arm64 + amazon2023-arm64 rhel-62-64-bit rhel-83-zseries ubuntu1604 ubuntu2204-64 + debian10 rhel-70-64-bit rhel-91-64-bit ubuntu1604-arm64 ubuntu2204-arm64 + debian11 rhel-71-ppc64el rhel-91-arm64 ubuntu1804-64 windows-test macOS:: $ # Set PYMONGOCRYPT_LIB for macOS: - $ export PYMONGOCRYPT_LIB=$(pwd)/libmongocrypt-all/macos/nocrypto/lib/libmongocrypt.dylib + $ export PYMONGOCRYPT_LIB=$(pwd)/libmongocrypt-all/macos/lib/libmongocrypt.dylib $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" - 1.2.1 + 1.9.0 Windows:: $ # Set PYMONGOCRYPT_LIB for Windows: - $ chmod +x $(pwd)/libmongocrypt-all/windows-test/nocrypto/bin/mongocrypt.dll - $ export PYMONGOCRYPT_LIB=$(pwd)/libmongocrypt-all/windows-test/nocrypto/bin/mongocrypt.dll + $ chmod +x $(pwd)/libmongocrypt-all/windows-test/bin/mongocrypt.dll + $ export PYMONGOCRYPT_LIB=$(pwd)/libmongocrypt-all/windows-test/bin/mongocrypt.dll $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" - 1.2.1 + 1.9.0 + +Linux: set the libmongocrypt build for your platform, for example for Ubuntu 22.04 x86_64:: -Linux:: + $ # Set PYMONGOCRYPT_LIB for Ubuntu 22.04 x86_64: + $ export PYMONGOCRYPT_LIB=$(pwd)/libmongocrypt-all/ubuntu2204-64/lib/libmongocrypt.so + $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" + 1.9.0 + $ # Check that native crypto is enabled for better performance: + $ python -c 'from pymongocrypt.binding import lib;print(lib.mongocrypt_is_crypto_available())' + True + +Note if your Linux platform is not available, the generic RHEL 6.2 x86_64 "nocrypto" build +should still be compatible however the "nocrypto" build will result in lower performance +for encryption and decryption:: $ # Set PYMONGOCRYPT_LIB for RHEL 6.2 x86_64: $ export PYMONGOCRYPT_LIB=$(pwd)/libmongocrypt-all/rhel-62-64-bit/nocrypto/lib64/libmongocrypt.so $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" - 1.2.1 + 1.9.0 + $ python -c 'from pymongocrypt.binding import lib;print(lib.mongocrypt_is_crypto_available())' + False + +Other methods of installation (brew, rpm, yum, apt-get, deb, etc...) are documented here: +https://www.mongodb.com/docs/manual/core/csfle/reference/libmongocrypt/#linux-installation Dependencies ============ -PyMongoCrypt supports Python 3.7+ and PyPy3.7+. +PyMongoCrypt supports Python 3.8+ and PyPy3.9+. PyMongoCrypt requires `cffi `_ and `cryptography `_. @@ -163,11 +184,11 @@ installed you will see an error like this: from pymongocrypt.binding import libmongocrypt_version, lib File "pymongocrypt/binding.py", line 803, in lib = ffi.dlopen(os.environ.get('PYMONGOCRYPT_LIB', 'mongocrypt')) - File "/.../lib/python3.7/site-packages/cffi/api.py", line 146, in dlopen + File "/.../lib/python3.8/site-packages/cffi/api.py", line 146, in dlopen lib, function_cache = _make_ffi_library(self, name, flags) - File "/.../lib/python3.7/site-packages/cffi/api.py", line 828, in _make_ffi_library + File "/.../lib/python3.8/site-packages/cffi/api.py", line 828, in _make_ffi_library backendlib = _load_backend_lib(backend, libname, flags) - File "/.../lib/python3.7/site-packages/cffi/api.py", line 823, in _load_backend_lib + File "/.../lib/python3.8/site-packages/cffi/api.py", line 823, in _load_backend_lib raise OSError(msg) OSError: ctypes.util.find_library() did not manage to locate a library called 'mongocrypt' @@ -178,7 +199,7 @@ variables, like ``LD_LIBRARY_PATH``. For example:: $ export PYMONGOCRYPT_LIB='/path/to/libmongocrypt.so' $ python -c "import pymongocrypt; print(pymongocrypt.libmongocrypt_version())" - 1.2.1 + 1.9.0 Testing ======= diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/RELEASE.rst b/ext/libmongocrypt/libmongocrypt/bindings/python/RELEASE.rst index d6755ec..a49a0f6 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/RELEASE.rst +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/RELEASE.rst @@ -41,7 +41,7 @@ Docker and a Windows machine. -REVISION=$(git rev-list -n 1 1.0.0) +REVISION=$(git rev-list -n 1 1.0.1) -#. Add a changlog entry for this release in CHANGELOG.rst. +#. Add a changelog entry for this release in CHANGELOG.rst. #. Bump "__version__" in ``pymongocrypt/version.py``. #. After merging the PR, clone the repository and check out the commit with the version change. @@ -51,25 +51,9 @@ Docker and a Windows machine. $ git tag -a "pymongocrypt-" -m "pymongocrypt-.tar.gz - pymongocrypt--py2.py3-none-manylinux2010_x86_64.whl - pymongocrypt--py2.py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl - pymongocrypt--py2.py3-none-macosx_10_14_x86_64.whl - pymongocrypt--py2.py3-none-macosx_11_0_universal2.whl - pymongocrypt--py2.py3-none-win_amd64.whl - -#. Upload all the release packages to PyPI with twine:: - - $ python3 -m twine upload dist/* +#. Pushing a tag will trigger the release process on GitHub Actions that will require a member + of the team to authorize the deployment. Navigate to https://github.com/mongodb/libmongocrypt/actions/workflows/release-python.yml + and wait for the publish to complete. #. Create a new PR against the same ticket to update version to a ``.dev0`` version. @@ -84,10 +68,10 @@ Manually Creating Wheels $ git clone git@github.com:mongodb/libmongocrypt.git $ cd libmongocrypt/bindings/python $ git checkout "pymongocrypt " - $ MACOS_TARGET=macos_x86_64 PYTHON= ./release.sh + $ MACOS_TARGET=macos_x86_64 PYTHON= ./release.sh $ PYTHON= ./release.sh - Make sure to run using the official binaries for Python 3.7 and 3.10. You + Make sure to run using the official binaries for Python 3.8 and 3.10. You should end up with the same files created by Evergreen (except for the Windows wheel). #. To build the release package for Windows, launch a windows-64-vsMulti-small @@ -103,5 +87,3 @@ Manually Creating Wheels $ ls dist pymongocrypt--py2.py3-none-win_amd64.whl - - diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/build-manylinux-wheel.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/build-manylinux-wheel.sh index a6e1ec1..e93b550 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/build-manylinux-wheel.sh +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/build-manylinux-wheel.sh @@ -1,16 +1,7 @@ #!/bin/bash -ex cd /python -# Compile wheel -# https://github.com/pypa/manylinux/issues/49 -rm -rf build -/opt/python/cp37-cp37m/bin/python setup.py bdist_wheel - -# Audit wheels and write manylinux tag -for whl in dist/*.whl; do - # Skip already built manylinux wheels. - if [[ "$whl" != *"manylinux"* ]]; then - auditwheel repair $whl -w dist - rm $whl - fi -done +mkdir /tmp/wheelhouse +/opt/python/cp38-cp38/bin/python -m build --wheel --outdir /tmp/wheelhouse +# Audit wheels and repair manylinux tags +auditwheel repair /tmp/wheelhouse/*.whl -w dist diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/hatch_build.py b/ext/libmongocrypt/libmongocrypt/bindings/python/hatch_build.py new file mode 100644 index 0000000..1ea6c29 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/hatch_build.py @@ -0,0 +1,36 @@ +"""A custom hatch build hook for pymongo.""" +from __future__ import annotations + +import os +import sys +from pathlib import Path + +from hatchling.builders.hooks.plugin.interface import BuildHookInterface + + +class CustomHook(BuildHookInterface): + """The pymongocrypt build hook.""" + + def initialize(self, version, build_data): + """Initialize the hook.""" + if self.target_name == "sdist": + return + + # Ensure wheel is marked as binary. + # On linux, we use auditwheel to set the name. + if sys.platform == "darwin": + os.environ["MACOSX_DEPLOYMENT_TARGET"] = "11.0" + build_data["tag"] = "py3-none-macosx_11_0_universal2" + patt = ".dylib" + elif os.name == "nt": + build_data["tag"] = "py3-none-win_amd64" + patt = ".dll" + else: + patt = ".so" + + here = Path(__file__).parent.resolve() + dpath = here / "pymongocrypt" + for fpath in dpath.glob(f"*{patt}"): + relpath = os.path.relpath(fpath, here) + build_data["artifacts"].append(relpath) + build_data["force_include"][relpath] = relpath diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/libmongocrypt-version.txt b/ext/libmongocrypt/libmongocrypt/bindings/python/libmongocrypt-version.txt new file mode 100644 index 0000000..4dae298 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/libmongocrypt-version.txt @@ -0,0 +1 @@ +1.10.1 diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/__init__.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/__init__.py index 9453cc7..a8eb966 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/__init__.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/__init__.py @@ -12,5 +12,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -from pymongocrypt.binding import libmongocrypt_version, lib -from pymongocrypt.version import __version__ +from pymongocrypt.binding import lib, libmongocrypt_version # noqa: F401 +from pymongocrypt.version import __version__ # noqa: F401 diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/auto_encrypter.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/auto_encrypter.py new file mode 100644 index 0000000..37d536b --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/auto_encrypter.py @@ -0,0 +1,61 @@ +# Copyright 2024-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. + +from pymongocrypt.asynchronous.state_machine import run_state_machine +from pymongocrypt.mongocrypt import MongoCrypt + + +class AsyncAutoEncrypter: + def __init__(self, callback, mongo_crypt_opts): + """Encrypts and decrypts MongoDB commands. + + This class is used by a driver to support automatic encryption and + decryption of MongoDB commands. + + :Parameters: + - `callback`: A :class:`MongoCryptCallback`. + - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. + """ + self.callback = callback + self.mongocrypt = MongoCrypt(mongo_crypt_opts, callback) + + async def encrypt(self, database, cmd): + """Encrypt a MongoDB command. + + :Parameters: + - `database`: The database for this command. + - `cmd`: A MongoDB command as BSON. + + :Returns: + The encrypted command. + """ + with self.mongocrypt.encryption_context(database, cmd) as ctx: + return await run_state_machine(ctx, self.callback) + + async def decrypt(self, response): + """Decrypt a MongoDB command response. + + :Parameters: + - `response`: A MongoDB command response as BSON. + + :Returns: + The decrypted command response. + """ + with self.mongocrypt.decryption_context(response) as ctx: + return await run_state_machine(ctx, self.callback) + + async def close(self): + """Cleanup resources.""" + self.mongocrypt.close() + await self.callback.close() diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/credentials.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/credentials.py new file mode 100644 index 0000000..2f81dc0 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/credentials.py @@ -0,0 +1,156 @@ +# Copyright 2024-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. +import os +from collections import namedtuple +from datetime import datetime, timedelta, timezone + +try: + from pymongo_auth_aws.auth import aws_temp_credentials + + _HAVE_AUTH_AWS = True +except ImportError: + _HAVE_AUTH_AWS = False + +import httpx + +from pymongocrypt.errors import MongoCryptError + +_azure_creds = namedtuple("_azure_creds", ["access_token", "expires_utc"]) +_azure_creds_cache = None + + +async def _get_gcp_credentials(): + """Get on-demand GCP credentials""" + metadata_host = os.getenv("GCE_METADATA_HOST") or "metadata.google.internal" + url = ( + "http://%s/computeMetadata/v1/instance/service-accounts/default/token" + % metadata_host + ) + + headers = {"Metadata-Flavor": "Google"} + client = httpx.AsyncClient() + try: + response = await client.get(url, headers=headers) + except Exception as e: + msg = "unable to retrieve GCP credentials: %s" % e + raise MongoCryptError(msg) from e + finally: + await client.aclose() + + if response.status_code != 200: + msg = f"Unable to retrieve GCP credentials: expected StatusCode 200, got StatusCode: {response.status_code}. Response body:\n{response.content}" + raise MongoCryptError(msg) + try: + data = response.json() + except Exception as e: + raise MongoCryptError( + f"unable to retrieve GCP credentials: error reading response body\n{response.content}" + ) from e + + if not data.get("access_token"): + msg = ( + "unable to retrieve GCP credentials: got unexpected empty accessToken from GCP Metadata Server. Response body: %s" + % response.content + ) + raise MongoCryptError(msg) + + return {"accessToken": data["access_token"]} + + +async def _get_azure_credentials(): + """Get on-demand Azure credentials""" + global _azure_creds_cache + # Credentials are considered expired when: Expiration - now < 1 mins. + creds = _azure_creds_cache + if creds: + if creds.expires_utc - datetime.now(tz=timezone.utc) < timedelta(seconds=60): + _azure_creds_cache = None + else: + return {"accessToken": creds.access_token} + + url = "http://169.254.169.254/metadata/identity/oauth2/token" + url += "?api-version=2018-02-01" + url += "&resource=https://vault.azure.net" + headers = {"Metadata": "true", "Accept": "application/json"} + client = httpx.AsyncClient() + try: + response = await client.get(url, headers=headers) + except Exception as e: + msg = "Failed to acquire IMDS access token: %s" % e + raise MongoCryptError(msg) from e + finally: + await client.aclose() + + if response.status_code != 200: + msg = "Failed to acquire IMDS access token." + raise MongoCryptError(msg) + try: + data = response.json() + except Exception as e: + raise MongoCryptError("Azure IMDS response must be in JSON format.") from e + + for key in ["access_token", "expires_in"]: + if not data.get(key): + msg = "Azure IMDS response must contain %s, but was %s." + msg = msg % (key, response.content) + raise MongoCryptError(msg) + + try: + expires_in = int(data["expires_in"]) + except ValueError as e: + raise MongoCryptError( + 'Azure IMDS response must contain "expires_in" integer, but was %s.' + % response.content + ) from e + + expires_utc = datetime.now(tz=timezone.utc) + timedelta(seconds=expires_in) + _azure_creds_cache = _azure_creds(data["access_token"], expires_utc) + return {"accessToken": data["access_token"]} + + +async def _ask_for_kms_credentials(kms_providers): + """Get on-demand kms credentials. + + This is a separate function so it can be overridden in unit tests.""" + global _azure_creds_cache + on_demand_aws = "aws" in kms_providers and not len(kms_providers["aws"]) + on_demand_gcp = "gcp" in kms_providers and not len(kms_providers["gcp"]) + on_demand_azure = "azure" in kms_providers and not len(kms_providers["azure"]) + + if not any([on_demand_aws, on_demand_gcp, on_demand_azure]): + return {} + creds = {} + if on_demand_aws: + if not _HAVE_AUTH_AWS: + raise RuntimeError( + "On-demand AWS credentials require pymongo-auth-aws: " + "install with: python -m pip install 'pymongo[aws]'" + ) + aws_creds = aws_temp_credentials() + creds_dict = { + "accessKeyId": aws_creds.username, + "secretAccessKey": aws_creds.password, + } + if aws_creds.token: + creds_dict["sessionToken"] = aws_creds.token + creds["aws"] = creds_dict + if on_demand_gcp: + creds["gcp"] = await _get_gcp_credentials() + if on_demand_azure: + try: + creds["azure"] = await _get_azure_credentials() + except Exception: + _azure_creds_cache = None + raise + return creds diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/explicit_encrypter.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/explicit_encrypter.py new file mode 100644 index 0000000..dcab42d --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/explicit_encrypter.py @@ -0,0 +1,156 @@ +# Copyright 2024-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. + +from pymongocrypt.asynchronous.state_machine import run_state_machine +from pymongocrypt.mongocrypt import MongoCrypt +from pymongocrypt.options import DataKeyOpts, ExplicitEncryptOpts + + +class AsyncExplicitEncrypter: + def __init__(self, callback, mongo_crypt_opts): + """Encrypts and decrypts BSON values. + + This class is used by a driver to support explicit encryption and + decryption of individual fields in a BSON document. + + :Parameters: + - `callback`: A :class:`MongoCryptCallback`. + - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. + """ + self.callback = callback + if mongo_crypt_opts.schema_map is not None: + raise ValueError("mongo_crypt_opts.schema_map must be None") + self.mongocrypt = MongoCrypt(mongo_crypt_opts, callback) + + async def create_data_key( + self, kms_provider, master_key=None, key_alt_names=None, key_material=None + ): + """Creates a data key used for explicit encryption. + + :Parameters: + - `kms_provider`: The KMS provider to use. Supported values are + "aws", "azure", "gcp", "kmip", "local", or a named provider like + "kmip:name". + - `master_key`: See class:`DataKeyOpts`. + - `key_alt_names` (optional): An optional list of string alternate + names used to reference a key. If a key is created with alternate + names, then encryption may refer to the key by the unique + alternate name instead of by ``_id``. + - `key_material`: (optional) See class:`DataKeyOpts`. + + :Returns: + The _id of the created data key document. + """ + # CDRIVER-3275 each key_alt_name needs to be wrapped in a bson + # document. + encoded_names = [] + if key_alt_names is not None: + for name in key_alt_names: + encoded_names.append(self.callback.bson_encode({"keyAltName": name})) + + if key_material is not None: + key_material = self.callback.bson_encode({"keyMaterial": key_material}) + + opts = DataKeyOpts(master_key, encoded_names, key_material) + with self.mongocrypt.data_key_context(kms_provider, opts) as ctx: + key = await run_state_machine(ctx, self.callback) + return await self.callback.insert_data_key(key) + + async def rewrap_many_data_key(self, filter, provider=None, master_key=None): + """Decrypts and encrypts all matching data keys with a possibly new `master_key` value. + + :Parameters: + - `filter`: A document used to filter the data keys. + - `provider`: (optional) The name of a different kms provider. + - `master_key`: Optional document for the given provider. + + :Returns: + A binary document with the rewrap data. + """ + with self.mongocrypt.rewrap_many_data_key_context( + filter, provider, master_key + ) as ctx: + return await run_state_machine(ctx, self.callback) + + async def encrypt( + self, + value, + algorithm, + key_id=None, + key_alt_name=None, + query_type=None, + contention_factor=None, + range_opts=None, + is_expression=False, + ): + """Encrypts a BSON value. + + Note that exactly one of ``key_id`` or ``key_alt_name`` must be + provided. + + :Parameters: + - `value` (bytes): The BSON value to encrypt. + - `algorithm` (string): The encryption algorithm to use. See + :class:`Algorithm` for some valid options. + - `key_id` (bytes): The bytes of the binary subtype 4 ``_id`` data + key. For example, ``uuid.bytes`` or ``bytes(bson_binary)``. + - `key_alt_name` (string): Identifies a key vault document by + 'keyAltName'. + - `query_type` (str): The query type to execute. + - `contention_factor` (int): The contention factor to use + when the algorithm is "Indexed". + - `range_opts` (bytes): Options for explicit encryption + with the "range" algorithm encoded as a BSON document. + - `is_expression` (boolean): True if this is an encryptExpression() + context. Defaults to False. + + :Returns: + The encrypted BSON value. + + .. versionchanged:: 1.3 + Added the `query_type` and `contention_factor` parameters. + .. versionchanged:: 1.5 + Added the `range_opts` and `is_expression` parameters. + """ + # CDRIVER-3275 key_alt_name needs to be wrapped in a bson document. + if key_alt_name is not None: + key_alt_name = self.callback.bson_encode({"keyAltName": key_alt_name}) + opts = ExplicitEncryptOpts( + algorithm, + key_id, + key_alt_name, + query_type, + contention_factor, + range_opts, + is_expression, + ) + with self.mongocrypt.explicit_encryption_context(value, opts) as ctx: + return await run_state_machine(ctx, self.callback) + + async def decrypt(self, value): + """Decrypts a BSON value. + + :Parameters: + - `value`: The encoded document to decrypt, which must be in the + form { "v" : encrypted BSON value }}. + + :Returns: + The decrypted BSON value. + """ + with self.mongocrypt.explicit_decryption_context(value) as ctx: + return await run_state_machine(ctx, self.callback) + + def close(self): + """Cleanup resources.""" + self.mongocrypt.close() diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/state_machine.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/state_machine.py new file mode 100644 index 0000000..f1a391d --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/state_machine.py @@ -0,0 +1,149 @@ +# Copyright 2024-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. + +from abc import abstractmethod + +from pymongocrypt.asynchronous.credentials import _ask_for_kms_credentials +from pymongocrypt.binding import lib +from pymongocrypt.compat import ABC +from pymongocrypt.errors import MongoCryptError + + +class AsyncMongoCryptCallback(ABC): + """Callback ABC to perform I/O on behalf of libbmongocrypt.""" + + @abstractmethod + async def kms_request(self, kms_context): + """Complete a KMS request. + + :Parameters: + - `kms_context`: A :class:`MongoCryptKmsContext`. + + :Returns: + None + """ + + @abstractmethod + async def collection_info(self, database, filter): + """Get the collection info for a namespace. + + The returned collection info is passed to libmongocrypt which reads + the JSON schema. + + :Parameters: + - `database`: The database on which to run listCollections. + - `filter`: The filter to pass to listCollections. + + :Returns: + The first document from the listCollections command response as BSON. + """ + + @abstractmethod + async def mark_command(self, database, cmd): + """Mark a command for encryption. + + :Parameters: + - `database`: The database on which to run this command. + - `cmd`: The BSON command to run. + + :Returns: + The marked command response from mongocryptd. + """ + + @abstractmethod + async def fetch_keys(self, filter): + """Yields one or more keys from the key vault. + + :Parameters: + - `filter`: The filter to pass to find. + + :Returns: + A generator which yields the requested keys from the key vault. + """ + + @abstractmethod + async def insert_data_key(self, data_key): + """Insert a data key into the key vault. + + :Parameters: + - `data_key`: The data key document to insert. + + :Returns: + The _id of the inserted data key document. + """ + + @abstractmethod + def bson_encode(self, doc): + """Encode a document to BSON. + + A document can be any mapping type (like :class:`dict`). + + :Parameters: + - `doc`: mapping type representing a document + + :Returns: + The encoded BSON bytes. + """ + + @abstractmethod + async def close(self): + """Release resources.""" + + +async def run_state_machine(ctx, callback): + """Run the libmongocrypt state machine until completion. + + :Parameters: + - `ctx`: A :class:`MongoCryptContext`. + - `callback`: A :class:`AsyncMongoCryptCallback`. + + :Returns: + The completed libmongocrypt operation. + """ + while True: + state = ctx.state + # Check for terminal states first. + if state == lib.MONGOCRYPT_CTX_ERROR: + ctx._raise_from_status() + elif state == lib.MONGOCRYPT_CTX_READY: + return ctx.finish() + elif state == lib.MONGOCRYPT_CTX_DONE: + return None + + if state == lib.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: + list_colls_filter = ctx.mongo_operation() + coll_info = await callback.collection_info(ctx.database, list_colls_filter) + if coll_info: + ctx.add_mongo_operation_result(coll_info) + ctx.complete_mongo_operation() + elif state == lib.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: + mongocryptd_cmd = ctx.mongo_operation() + result = await callback.mark_command(ctx.database, mongocryptd_cmd) + ctx.add_mongo_operation_result(result) + ctx.complete_mongo_operation() + elif state == lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS: + key_filter = ctx.mongo_operation() + for key in await callback.fetch_keys(key_filter): + ctx.add_mongo_operation_result(key) + ctx.complete_mongo_operation() + elif state == lib.MONGOCRYPT_CTX_NEED_KMS: + for kms_ctx in ctx.kms_contexts(): + with kms_ctx: + await callback.kms_request(kms_ctx) + ctx.complete_kms() + elif state == lib.MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: + creds = await _ask_for_kms_credentials(ctx.kms_providers) + ctx.provide_kms_providers(callback.bson_encode(creds)) + else: + raise MongoCryptError(f"unknown state: {state}") diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/auto_encrypter.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/auto_encrypter.py index 2e4a0da..4cdfd4e 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/auto_encrypter.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/auto_encrypter.py @@ -12,50 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from pymongocrypt.mongocrypt import MongoCrypt -from pymongocrypt.state_machine import run_state_machine +# Alias file for import compatibility - -class AutoEncrypter(object): - def __init__(self, callback, mongo_crypt_opts): - """Encrypts and decrypts MongoDB commands. - - This class is used by a driver to support automatic encryption and - decryption of MongoDB commands. - - :Parameters: - - `callback`: A :class:`MongoCryptCallback`. - - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. - """ - self.callback = callback - self.mongocrypt = MongoCrypt(mongo_crypt_opts, callback) - - def encrypt(self, database, cmd): - """Encrypt a MongoDB command. - - :Parameters: - - `database`: The database for this command. - - `cmd`: A MongoDB command as BSON. - - :Returns: - The encrypted command. - """ - with self.mongocrypt.encryption_context(database, cmd) as ctx: - return run_state_machine(ctx, self.callback) - - def decrypt(self, response): - """Decrypt a MongoDB command response. - - :Parameters: - - `response`: A MongoDB command response as BSON. - - :Returns: - The decrypted command response. - """ - with self.mongocrypt.decryption_context(response) as ctx: - return run_state_machine(ctx, self.callback) - - def close(self): - """Cleanup resources.""" - self.mongocrypt.close() - self.callback.close() +from pymongocrypt.synchronous.auto_encrypter import * diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binary.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binary.py index 72b0edf..b481e36 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binary.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binary.py @@ -20,30 +20,29 @@ def _to_bytes(mongocrypt_binary): """Returns this mongocrypt_binary_t as bytes.""" - data = lib.mongocrypt_binary_data(mongocrypt_binary) + data = mongocrypt_binary.data if data == ffi.NULL: - raise MongoCryptError('mongocrypt_binary_data returned NULL') - data_len = lib.mongocrypt_binary_len(mongocrypt_binary) - return ffi.unpack(ffi.cast("char*", data), data_len) + raise MongoCryptError("mongocrypt_binary_t.data returned NULL") + return ffi.unpack(ffi.cast("char*", data), mongocrypt_binary.len) def _write_bytes(mongocrypt_binary, data): """Writes the given data to a mongocrypt_binary_t.""" - buf = lib.mongocrypt_binary_data(mongocrypt_binary) + buf = mongocrypt_binary.data if buf == ffi.NULL: - raise MongoCryptError('mongocrypt_binary_data returned NULL') + raise MongoCryptError("mongocrypt_binary_t.data returned NULL") ffi.memmove(buf, data, len(data)) + mongocrypt_binary.len = len(data) -class _MongoCryptBinary(object): +class _MongoCryptBinary: __slots__ = ("bin",) def __init__(self, binary): """Wraps a mongocrypt_binary_t.""" if binary == ffi.NULL: - raise MongoCryptError( - "unable to create new mongocrypt_binary object") + raise MongoCryptError("unable to create new mongocrypt_binary object") self.bin = binary def _close(self): @@ -60,11 +59,10 @@ def __exit__(self, exc_type, exc_val, exc_tb): def to_bytes(self): """Returns this mongocrypt_binary_t as bytes.""" - data = lib.mongocrypt_binary_data(self.bin) + data = self.bin.data if data == ffi.NULL: - return b'' - data_len = lib.mongocrypt_binary_len(self.bin) - return ffi.unpack(ffi.cast("char*", data), data_len) + return b"" + return ffi.unpack(ffi.cast("char*", data), self.bin.len) class MongoCryptBinaryOut(_MongoCryptBinary): @@ -72,7 +70,7 @@ class MongoCryptBinaryOut(_MongoCryptBinary): def __init__(self): """Wraps a mongocrypt_binary_t.""" - super(MongoCryptBinaryOut, self).__init__(lib.mongocrypt_binary_new()) + super().__init__(lib.mongocrypt_binary_new()) class MongoCryptBinaryIn(_MongoCryptBinary): @@ -83,12 +81,11 @@ def __init__(self, data): # mongocrypt_binary_t does not own the data it is passed so we need to # create a separate reference to keep the data alive. self.cref = ffi.from_buffer("uint8_t[]", data) - super(MongoCryptBinaryIn, self).__init__( - lib.mongocrypt_binary_new_from_data(self.cref, len(data))) + super().__init__(lib.mongocrypt_binary_new_from_data(self.cref, len(data))) def _close(self): """Cleanup resources.""" - super(MongoCryptBinaryIn, self)._close() + super()._close() if self.cref is not None: ffi.release(self.cref) self.cref = None diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py index 35b35ce..5394e2a 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py @@ -15,25 +15,23 @@ import os import os.path import sys +from pathlib import Path import cffi +from packaging.version import Version -from pymongocrypt.compat import PY3 from pymongocrypt.version import _MIN_LIBMONGOCRYPT_VERSION -try: - from pkg_resources import parse_version as _parse_version -except ImportError: - from distutils.version import LooseVersion as _LooseVersion - def _parse_version(version): - return _LooseVersion(version) +def _parse_version(version): + return Version(version) ffi = cffi.FFI() # Generated with strip_header.py -ffi.cdef("""/* +ffi.cdef( + """/* * Copyright 2019-present MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -67,6 +65,16 @@ def _parse_version(version): */ const char *mongocrypt_version(uint32_t *len); +/** + * Returns true if libmongocrypt was built with native crypto support. + * + * If libmongocrypt was not built with native crypto support, setting crypto + * hooks is required. + * + * @returns True if libmongocrypt was built with native crypto support. + */ +bool mongocrypt_is_crypto_available(void); + /** * A non-owning view of a byte buffer. * @@ -88,8 +96,14 @@ def _parse_version(version): * mongocrypt_ctx_mongo_op guarantees that the viewed data of * mongocrypt_binary_t is valid until the parent ctx is destroyed with @ref * mongocrypt_ctx_destroy. + * + * The `mongocrypt_binary_t` struct definition is public. + * Consumers may rely on the struct layout. */ -typedef struct _mongocrypt_binary_t mongocrypt_binary_t; +typedef struct _mongocrypt_binary_t { + void *data; + uint32_t len; +} mongocrypt_binary_t; /** * Create a new non-owning view of a buffer (data + length). @@ -453,6 +467,17 @@ def _parse_version(version): */ void mongocrypt_setopt_use_need_kms_credentials_state(mongocrypt_t *crypt); +/** + * @brief Opt-into handling the MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB state. + * + * A context enters the MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB state when + * processing a `bulkWrite` command. The target database of the `bulkWrite` may differ from the command database + * ("admin"). + * + * @param[in] crypt The @ref mongocrypt_t object to update + */ +void mongocrypt_setopt_use_need_mongo_collinfo_with_db_state(mongocrypt_t *crypt); + /** * Initialize new @ref mongocrypt_t object. * @@ -510,7 +535,7 @@ def _parse_version(version): * @brief Obtain a 64-bit constant encoding the version of the loaded * crypt_shared library, if available. * - * @param[in] crypt The mongocrypt_t object after a successul call to + * @param[in] crypt The mongocrypt_t object after a successful call to * mongocrypt_init. * * @return A 64-bit encoded version number, with the version encoded as four @@ -639,9 +664,8 @@ def _parse_version(version): /// String constant for setopt_algorithm "Random" encryption /// String constant for setopt_algorithm "Indexed" explicit encryption /// String constant for setopt_algorithm "Unindexed" explicit encryption -/// String constant for setopt_algorithm "rangePreview" explicit encryption -/// NOTE: The RangePreview algorithm is experimental only. It is not intended -/// for public use. +// DEPRECATED: support "RangePreview" has been removed in favor of "range". +// NOTE: "Range" is currently unstable API and subject to backwards breaking changes. /** * Identify the AWS KMS master key to use for creating a data key. @@ -823,9 +847,9 @@ def _parse_version(version): /** * Explicit helper method to encrypt a Match Expression or Aggregate Expression. * Contexts created for explicit encryption will not go through mongocryptd. - * Requires query_type to be "rangePreview". - * NOTE: The RangePreview algorithm is experimental only. It is not intended for - * public use. + * Requires query_type to be "range". + * + * NOTE: "range" is currently unstable API and subject to backwards breaking changes. * * This method expects the passed-in BSON to be of the form: * { "v" : FLE2RangeFindDriverSpec } @@ -918,9 +942,10 @@ def _parse_version(version): */ typedef enum { MONGOCRYPT_CTX_ERROR = 0, - MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /* run on main MongoClient */ - MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /* run on mongocryptd. */ - MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /* run on key vault */ + MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /* run on main MongoClient */ + MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB = 8, /* run on main MongoClient */ + MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /* run on mongocryptd. */ + MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /* run on key vault */ MONGOCRYPT_CTX_NEED_KMS = 4, MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS = 7, /* fetch/renew KMS credentials */ MONGOCRYPT_CTX_READY = 5, /* ready for encryption/decryption */ @@ -940,7 +965,7 @@ def _parse_version(version): * is in MONGOCRYPT_CTX_NEED_MONGO_* states. * * @p op_bson is a BSON document to be used for the operation. - * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a listCollections filter. + * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO(_WITH_DB) it is a listCollections filter. * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a find filter. * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a command to send to * mongocryptd. @@ -957,13 +982,28 @@ def _parse_version(version): */ bool mongocrypt_ctx_mongo_op(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *op_bson); +/** + * Get the database to run the mongo operation. + * + * Only applies when mongocrypt_ctx_t is in the state: + * MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB. + * + * The lifetime of the returned string is tied to the lifetime of @p ctx. It is + * valid until @ref mongocrypt_ctx_destroy is called. + * + * @param[in] ctx The @ref mongocrypt_ctx_t object. + * @returns A string or NULL. If NULL, an error status is set. Retrieve it with + * @ref mongocrypt_ctx_status + */ +const char *mongocrypt_ctx_mongo_db(mongocrypt_ctx_t *ctx); + /** * Feed a BSON reply or result when mongocrypt_ctx_t is in * MONGOCRYPT_CTX_NEED_MONGO_* states. This may be called multiple times * depending on the operation. * * reply is a BSON document result being fed back for this operation. - * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a doc from a listCollections + * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO(_WITH_DB) it is a doc from a listCollections * cursor. (Note, if listCollections returned no result, do not call this * function.) * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a doc from a find cursor. @@ -1176,7 +1216,7 @@ def _parse_version(version): * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status - * with a message indiciating the error using @ref mongocrypt_status_set. + * with a message indicating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_crypto_fn)(void *ctx, mongocrypt_binary_t *key, @@ -1201,7 +1241,7 @@ def _parse_version(version): * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status - * with a message indiciating the error using @ref mongocrypt_status_set. + * with a message indicating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_hmac_fn)(void *ctx, mongocrypt_binary_t *key, @@ -1220,7 +1260,7 @@ def _parse_version(version): * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status - * with a message indiciating the error using @ref mongocrypt_status_set. + * with a message indicating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_hash_fn)(void *ctx, mongocrypt_binary_t *in, @@ -1238,7 +1278,7 @@ def _parse_version(version): * @param[out] status An optional status to pass error messages. See @ref * mongocrypt_status_set. * @returns A boolean indicating success. If returning false, set @p status - * with a message indiciating the error using @ref mongocrypt_status_set. + * with a message indicating the error using @ref mongocrypt_status_set. */ typedef bool (*mongocrypt_random_fn)(void *ctx, mongocrypt_binary_t *out, uint32_t count, mongocrypt_status_t *status); @@ -1259,8 +1299,7 @@ def _parse_version(version): * operation. * @param[in] aes_256_ctr_decrypt The crypto callback function for decrypt * operation. - * @param[in] ctx A context passed as an argument to the crypto callback - * every invocation. + * @param[in] ctx Unused. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status @@ -1279,8 +1318,7 @@ def _parse_version(version): * @param[in] crypt The @ref mongocrypt_t object. * @param[in] aes_256_ecb_encrypt The crypto callback function for encrypt * operation. - * @param[in] ctx A context passed as an argument to the crypto callback - * every invocation. + * @param[in] ctx Unused. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status @@ -1320,6 +1358,17 @@ def _parse_version(version): */ void mongocrypt_setopt_bypass_query_analysis(mongocrypt_t *crypt); +/** + * DEPRECATED: Use of `mongocrypt_setopt_use_range_v2` is deprecated. Range V2 is always enabled. + * NOTE: "range" is currently unstable API and subject to backwards breaking changes. + * + * @param[in] crypt The @ref mongocrypt_t object. + * + * @returns A boolean indicating success. If false, an error status is set. + * Retrieve it with @ref mongocrypt_status + */ +bool mongocrypt_setopt_use_range_v2(mongocrypt_t *crypt); + /** * Set the contention factor used for explicit encryption. * The contention factor is only used for indexed Queryable Encryption. @@ -1362,16 +1411,16 @@ def _parse_version(version): bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t *ctx, const char *query_type, int len); /** - * Set options for explicit encryption with the "rangePreview" algorithm. - * NOTE: The RangePreview algorithm is experimental only. It is not intended for - * public use. + * Set options for explicit encryption with the "range" algorithm. + * NOTE: "range" is currently unstable API and subject to backwards breaking changes. * * @p opts is a BSON document of the form: * { * "min": Optional, * "max": Optional, * "sparsity": Int64, - * "precision": Optional + * "precision": Optional, + * "trimFactor": Optional * } * * @param[in] ctx The @ref mongocrypt_ctx_t object. @@ -1383,18 +1432,15 @@ def _parse_version(version): bool mongocrypt_ctx_setopt_algorithm_range(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *opts); /// String constants for setopt_query_type -// NOTE: The RangePreview algorithm is experimental only. It is not intended for -// public use. -""") - -if PY3: - def _to_string(cdata): - """Decode a cdata c-string to a Python str.""" - return ffi.string(cdata).decode() -else: - def _to_string(cdata): - """Decode a cdata c-string to a Python str.""" - return ffi.string(cdata) +// DEPRECATED: Support "rangePreview" has been removed in favor of "range". +/// NOTE: "range" is currently unstable API and subject to backwards breaking changes. +""" +) + + +def _to_string(cdata): + """Decode a cdata c-string to a Python str.""" + return ffi.string(cdata).decode() def libmongocrypt_version(): @@ -1408,18 +1454,19 @@ def libmongocrypt_version(): # export PYMONGOCRYPT_LIB='/path/to/libmongocrypt.so' # If the PYMONGOCRYPT_LIB is not set then load the embedded library and # fallback to the relying on a system installed library. -_base = os.path.dirname(os.path.realpath(__file__)) -if sys.platform == 'win32': - _path = os.path.join(_base, 'mongocrypt.dll') -elif sys.platform == 'darwin': - _path = os.path.join(_base, 'libmongocrypt.dylib') +_base = Path(os.path.realpath(__file__)).parent +if sys.platform == "win32": + _path = Path(_base) / "mongocrypt.dll" +elif sys.platform == "darwin": + _path = Path(_base) / "libmongocrypt.dylib" else: - _path = os.path.join(_base, 'libmongocrypt.so') + _path = Path(_base) / "libmongocrypt.so" -class _Library(object): +class _Library: """Helper class for delaying errors that would usually be raised at import time until the library is actually used.""" + def __init__(self, error): self._error = error @@ -1427,25 +1474,24 @@ def __getattr__(self, name): raise self._error -_PYMONGOCRYPT_LIB = os.environ.get('PYMONGOCRYPT_LIB') +_PYMONGOCRYPT_LIB = os.environ.get("PYMONGOCRYPT_LIB") try: if _PYMONGOCRYPT_LIB: lib = ffi.dlopen(_PYMONGOCRYPT_LIB) else: try: - lib = ffi.dlopen(_path) - except OSError as exc: + lib = ffi.dlopen(str(_path)) + except OSError: # Fallback to libmongocrypt installed on the system. - lib = ffi.dlopen('mongocrypt') + lib = ffi.dlopen("mongocrypt") except OSError as exc: # dlopen raises OSError when the library cannot be found. # Delay the error until the library is actually used. lib = _Library(exc) else: - # Check the libmongocrypt version when the library is found. - _limongocrypt_version = _parse_version(libmongocrypt_version()) - if _limongocrypt_version < _parse_version(_MIN_LIBMONGOCRYPT_VERSION): + _limongocrypt_version = Version(libmongocrypt_version()) + if _limongocrypt_version < Version(_MIN_LIBMONGOCRYPT_VERSION): exc = RuntimeError( - "Expected libmongocrypt version %s or greater, found %s" % ( - _MIN_LIBMONGOCRYPT_VERSION, libmongocrypt_version())) + f"Expected libmongocrypt version %s or greater, found {_MIN_LIBMONGOCRYPT_VERSION, libmongocrypt_version()}" + ) lib = _Library(exc) diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/compat.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/compat.py index 5a7a037..032ab63 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/compat.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/compat.py @@ -16,19 +16,21 @@ import sys -PY3 = sys.version_info[0] == 3 +PY3 = sys.version_info[0] >= 3 if PY3: from abc import ABC + unicode_type = str else: from abc import ABCMeta as _ABCMeta - ABC = _ABCMeta('ABC', (object,), {}) - unicode_type = unicode + + ABC = _ABCMeta("ABC", (object,), {}) + unicode_type = "unicode" def str_to_bytes(string): """Convert a str (or unicode) to bytes.""" if isinstance(string, bytes): return string - return string.encode('utf-8') + return string.encode("utf-8") diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/credentials.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/credentials.py index 4d3cc64..e4e039f 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/credentials.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/credentials.py @@ -11,126 +11,7 @@ # 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. -import os -from collections import namedtuple -from datetime import datetime, timedelta -try: - from pymongo_auth_aws.auth import aws_temp_credentials - _HAVE_AUTH_AWS = True -except ImportError: - _HAVE_AUTH_AWS = False +# Alias file for import compatibility -from pymongocrypt.errors import MongoCryptError - -import requests - - -_azure_creds = namedtuple("_azure_creds", ["access_token", "expires_in"]) -_azure_creds_cache = None - - -def _get_gcp_credentials(): - """Get on-demand GCP credentials""" - metadata_host = os.getenv("GCE_METADATA_HOST") or "metadata.google.internal" - url = "http://%s/computeMetadata/v1/instance/service-accounts/default/token" % metadata_host - - headers = {"Metadata-Flavor": "Google"} - try: - response = requests.get(url, headers=headers) - except Exception as e: - msg = "unable to retrieve GCP credentials: %s" % e - raise MongoCryptError(msg) - - if response.status_code != 200: - msg = "Unable to retrieve GCP credentials: expected StatusCode 200, got StatusCode: %s. Response body:\n%s" % (response.status_code, response.content) - raise MongoCryptError(msg) - try: - data = response.json() - except Exception: - raise MongoCryptError("unable to retrieve GCP credentials: error reading response body\n%s" % response.content) - - if not data.get("access_token"): - msg = "unable to retrieve GCP credentials: got unexpected empty accessToken from GCP Metadata Server. Response body: %s" % response.content - raise MongoCryptError(msg) - - return {'accessToken': data['access_token']} - - -def _get_azure_credentials(): - """Get on-demand Azure credentials""" - global _azure_creds_cache - # Credentials are considered expired when: Expiration - now < 1 mins. - creds = _azure_creds_cache - if creds: - if creds.expires_in - datetime.utcnow() < timedelta(seconds=60): - _azure_creds_cache = None - else: - return { 'accessToken': creds.access_token } - - url = "http://169.254.169.254/metadata/identity/oauth2/token" - url += "?api-version=2018-02-01" - url += "&resource=https://vault.azure.net" - headers = { "Metadata": "true", "Accept": "application/json" } - try: - response = requests.get(url, headers=headers) - except Exception as e: - msg = "Failed to acquire IMDS access token: %s" % e - raise MongoCryptError(msg) - - if response.status_code != 200: - msg = "Failed to acquire IMDS access token." - raise MongoCryptError(msg) - try: - data = response.json() - except Exception: - raise MongoCryptError("Azure IMDS response must be in JSON format.") - - for key in ["access_token", "expires_in"]: - if not data.get(key): - msg = "Azure IMDS response must contain %s, but was %s." - msg = msg % (key, response.content) - raise MongoCryptError(msg) - - try: - expires_in = int(data["expires_in"]) - except ValueError: - raise MongoCryptError('Azure IMDS response must contain "expires_in" integer, but was %s.' % response.content) - - expiration_time = datetime.utcnow() + timedelta(seconds=expires_in) - _azure_creds_cache = _azure_creds(data['access_token'], expiration_time) - return { 'accessToken': data['access_token'] } - - -def _ask_for_kms_credentials(kms_providers): - """Get on-demand kms credentials. - - This is a separate function so it can be overridden in unit tests.""" - global _azure_creds_cache - on_demand_aws = 'aws' in kms_providers and not len(kms_providers['aws']) - on_demand_gcp = 'gcp' in kms_providers and not len(kms_providers['gcp']) - on_demand_azure = 'azure' in kms_providers and not len(kms_providers['azure']) - - if not any([on_demand_aws, on_demand_gcp, on_demand_azure]): - return {} - creds = {} - if on_demand_aws: - if not _HAVE_AUTH_AWS: - raise RuntimeError( - "On-demand AWS credentials require pymongo-auth-aws: " - "install with: python -m pip install 'pymongo[aws]'" - ) - aws_creds = aws_temp_credentials() - creds_dict = {"accessKeyId": aws_creds.username, "secretAccessKey": aws_creds.password} - if aws_creds.token: - creds_dict["sessionToken"] = aws_creds.token - creds['aws'] = creds_dict - if on_demand_gcp: - creds['gcp'] = _get_gcp_credentials() - if on_demand_azure: - try: - creds['azure'] = _get_azure_credentials() - except Exception: - _azure_creds_cache = None - raise - return creds +from pymongocrypt.synchronous.credentials import * diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/crypto.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/crypto.py index b628e96..f013831 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/crypto.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/crypto.py @@ -20,7 +20,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cryptography.hazmat.primitives.hashes import Hash, SHA256, SHA512 +from cryptography.hazmat.primitives.hashes import SHA256, SHA512, Hash from cryptography.hazmat.primitives.hmac import HMAC from cryptography.hazmat.primitives.serialization import load_der_private_key @@ -35,18 +35,19 @@ def _callback_error_handler(exception, exc_value, tb): # if the whole function ran successfully but there was an error converting # the value returned: this occurs after the call)." if tb is not None: - status = tb.tb_frame.f_locals['status'] - msg = str_to_bytes(''.join(traceback.format_exception( - exception, exc_value, tb))) + status = tb.tb_frame.f_locals["status"] + msg = str_to_bytes( + "".join(traceback.format_exception(exception, exc_value, tb)) + ) lib.mongocrypt_status_set( - status, lib.MONGOCRYPT_STATUS_ERROR_CLIENT, 1, msg, -1) + status, lib.MONGOCRYPT_STATUS_ERROR_CLIENT, 1, msg, -1 + ) return False def _aes_256_encrypt(key, mode, input, output, bytes_written): - cipher = Cipher(algorithms.AES(_to_bytes(key)), mode, - backend=default_backend()) + cipher = Cipher(algorithms.AES(_to_bytes(key)), mode, backend=default_backend()) encryptor = cipher.encryptor() data = encryptor.update(_to_bytes(input)) + encryptor.finalize() _write_bytes(output, data) @@ -54,8 +55,7 @@ def _aes_256_encrypt(key, mode, input, output, bytes_written): def _aes_256_decrypt(key, mode, input, output, bytes_written): - cipher = Cipher(algorithms.AES(_to_bytes(key)), mode, - backend=default_backend()) + cipher = Cipher(algorithms.AES(_to_bytes(key)), mode, backend=default_backend()) decryptor = cipher.decryptor() data = decryptor.update(_to_bytes(input)) + decryptor.finalize() _write_bytes(output, data) @@ -66,7 +66,8 @@ def _aes_256_decrypt(key, mode, input, output, bytes_written): "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *," " mongocrypt_binary_t *, mongocrypt_binary_t *, uint32_t *," " mongocrypt_status_t *)", - onerror=_callback_error_handler) + onerror=_callback_error_handler, +) def aes_256_cbc_encrypt(ctx, key, iv, input, output, bytes_written, status): # Note that libmongocrypt pads the input before calling this method. _aes_256_encrypt(key, modes.CBC(_to_bytes(iv)), input, output, bytes_written) @@ -77,7 +78,8 @@ def aes_256_cbc_encrypt(ctx, key, iv, input, output, bytes_written, status): "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *," " mongocrypt_binary_t *, mongocrypt_binary_t *, uint32_t *," " mongocrypt_status_t *)", - onerror=_callback_error_handler) + onerror=_callback_error_handler, +) def aes_256_cbc_decrypt(ctx, key, iv, input, output, bytes_written, status): # Note that libmongocrypt pads the input before calling this method. _aes_256_decrypt(key, modes.CBC(_to_bytes(iv)), input, output, bytes_written) @@ -88,7 +90,8 @@ def aes_256_cbc_decrypt(ctx, key, iv, input, output, bytes_written, status): "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *," " mongocrypt_binary_t *, mongocrypt_binary_t *, uint32_t *," " mongocrypt_status_t *)", - onerror=_callback_error_handler) + onerror=_callback_error_handler, +) def aes_256_ctr_encrypt(ctx, key, iv, input, output, bytes_written, status): _aes_256_encrypt(key, modes.CTR(_to_bytes(iv)), input, output, bytes_written) return True @@ -98,7 +101,8 @@ def aes_256_ctr_encrypt(ctx, key, iv, input, output, bytes_written, status): "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *," " mongocrypt_binary_t *, mongocrypt_binary_t *, uint32_t *," " mongocrypt_status_t *)", - onerror=_callback_error_handler) + onerror=_callback_error_handler, +) def aes_256_ctr_decrypt(ctx, key, iv, input, output, bytes_written, status): _aes_256_decrypt(key, modes.CTR(_to_bytes(iv)), input, output, bytes_written) return True @@ -107,7 +111,8 @@ def aes_256_ctr_decrypt(ctx, key, iv, input, output, bytes_written, status): @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *, " " mongocrypt_binary_t *, mongocrypt_status_t *)", - onerror=_callback_error_handler) + onerror=_callback_error_handler, +) def hmac_sha_256(ctx, key, input, output, status): h = HMAC(_to_bytes(key), SHA256(), backend=default_backend()) h.update(_to_bytes(input)) @@ -119,7 +124,8 @@ def hmac_sha_256(ctx, key, input, output, status): @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *, " " mongocrypt_binary_t *, mongocrypt_status_t *)", - onerror=_callback_error_handler) + onerror=_callback_error_handler, +) def hmac_sha_512(ctx, key, input, output, status): h = HMAC(_to_bytes(key), SHA512(), backend=default_backend()) h.update(_to_bytes(input)) @@ -131,7 +137,8 @@ def hmac_sha_512(ctx, key, input, output, status): @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *, " " mongocrypt_status_t *)", - onerror=_callback_error_handler) + onerror=_callback_error_handler, +) def sha_256(ctx, input, output, status): digest = Hash(SHA256(), backend=default_backend()) digest.update(_to_bytes(input)) @@ -142,7 +149,8 @@ def sha_256(ctx, input, output, status): @ffi.callback( "bool(void *, mongocrypt_binary_t *, uint32_t, mongocrypt_status_t *)", - onerror=_callback_error_handler) + onerror=_callback_error_handler, +) def secure_random(ctx, output, count, status): data = os.urandom(int(count)) _write_bytes(output, data) @@ -152,11 +160,14 @@ def secure_random(ctx, output, count, status): @ffi.callback( "bool(void *, mongocrypt_binary_t *, mongocrypt_binary_t *, " " mongocrypt_binary_t *, mongocrypt_status_t *)", - onerror=_callback_error_handler) + onerror=_callback_error_handler, +) def sign_rsaes_pkcs1_v1_5(ctx, key, input, output, status): rsa_private_key = load_der_private_key( - _to_bytes(key), password=None, backend=default_backend()) + _to_bytes(key), password=None, backend=default_backend() + ) signature = rsa_private_key.sign( - _to_bytes(input), padding=padding.PKCS1v15(), algorithm=SHA256()) + _to_bytes(input), padding=padding.PKCS1v15(), algorithm=SHA256() + ) _write_bytes(output, signature) return True diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/errors.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/errors.py index df637bb..ae0c3b4 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/errors.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/errors.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from pymongocrypt.binding import ffi, lib, _to_string +from pymongocrypt.binding import _to_string, ffi, lib class MongoCryptError(Exception): @@ -23,7 +23,7 @@ def __init__(self, msg, code=-1): - `msg`: An error message. - `code`: The mongocrypt_status_t code. """ - super(MongoCryptError, self).__init__(msg) + super().__init__(msg) self.code = code @classmethod diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/explicit_encrypter.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/explicit_encrypter.py index f1b84d3..a4ad2e9 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/explicit_encrypter.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/explicit_encrypter.py @@ -12,237 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from pymongocrypt.mongocrypt import MongoCrypt -from pymongocrypt.state_machine import run_state_machine +# Alias file for import compatibility - -class ExplicitEncryptOpts(object): - def __init__(self, algorithm, key_id=None, key_alt_name=None, - query_type=None, contention_factor=None, range_opts=None, - is_expression=False): - """Options for explicit encryption. - - :Parameters: - - `algorithm` (str): The algorithm to use. - - `key_id`: The data key _id. - - `key_alt_name` (bytes): Identifies a key vault document by - 'keyAltName'. Must be BSON encoded document in the form: - { "keyAltName" : (BSON UTF8 value) } - - `query_type` (str): The query type to execute. - - `contention_factor` (int): The contention factor to use - when the algorithm is "Indexed". - - `range_opts` (bytes): Options for explicit encryption - with the "rangePreview" algorithm encoded as a BSON document. - - `is_expression` (boolean): True if this is an encryptExpression() - context. Defaults to False. - - .. versionchanged:: 1.3 - Added the `query_type` and `contention_factor` parameters. - .. versionchanged:: 1.5 - Added the `range_opts` and `is_expression` parameters. - """ - self.algorithm = algorithm - self.key_id = key_id - self.key_alt_name = key_alt_name - if query_type is not None: - if not isinstance(query_type, str): - raise TypeError( - 'query_type must be str or None, not: %r' % (type(query_type),)) - self.query_type = query_type - if contention_factor is not None and not isinstance(contention_factor, int): - raise TypeError( - 'contention_factor must be an int or None, not: %r' % (type(contention_factor),)) - self.contention_factor = contention_factor - if range_opts is not None and not isinstance(range_opts, bytes): - raise TypeError( - 'range_opts must be an bytes or None, not: %r' % (type(range_opts),)) - self.range_opts = range_opts - self.is_expression = is_expression - - -class DataKeyOpts(object): - def __init__(self, master_key=None, key_alt_names=None, key_material=None): - """Options for creating encryption keys. - - :Parameters: - - `master_key`: Identifies a KMS-specific key used to encrypt the - new data key. If the kmsProvider is "local" the `master_key` is - not applicable and may be omitted. - - If the `kms_provider` is "aws" it is required and has the - following fields:: - - - `region` (string): Required. The AWS region, e.g. "us-east-1". - - `key` (string): Required. The Amazon Resource Name (ARN) to - the AWS customer. - - `endpoint` (string): Optional. An alternate host to send KMS - requests to. May include port number, e.g. - "kms.us-east-1.amazonaws.com:443". - - If the `kms_provider` is "azure" it is required and has the - following fields:: - - - `keyVaultEndpoint` (string): Required. Host with optional - port, e.g. "example.vault.azure.net". - - `keyName` (string): Required. Key name in the key vault. - - `keyVersion` (string): Optional. Version of the key to use. - - If the `kms_provider` is "gcp" it is required and has the - following fields:: - - - `projectId` (string): Required. The Google cloud project ID. - - `location` (string): Required. The GCP location, e.g. "us-east1". - - `keyRing` (string): Required. Name of the key ring that contains - the key to use. - - `keyName` (string): Required. Name of the key to use. - - `keyVersion` (string): Optional. Version of the key to use. - - `endpoint` (string): Optional. Host with optional port. - Defaults to "cloudkms.googleapis.com". - - If the `kms_provider` is "kmip" it is optional and has the - following fields:: - - - `keyId` (string): Optional. `keyId` is the KMIP Unique - Identifier to a 96 byte KMIP Secret Data managed object. If - keyId is omitted, the driver creates a random 96 byte KMIP - Secret Data managed object. - - `endpoint` (string): Optional. Host with optional - port, e.g. "example.vault.azure.net:". - - - `key_alt_names`: An optional list of bytes suitable to be passed to - mongocrypt_ctx_setopt_key_alt_name. Each element must be BSON - encoded document in the form: { "keyAltName" : (BSON UTF8 value) } - - - `key_material`: An optional binary value of 96 bytes to use as - custom key material for the data key being created. If - ``key_material`` is given, the custom key material is used for - encrypting and decrypting data. Otherwise, the key material for the - new data key is generated from a cryptographically secure random - device. - """ - self.master_key = master_key - self.key_alt_names = key_alt_names - self.key_material = key_material - - -class ExplicitEncrypter(object): - def __init__(self, callback, mongo_crypt_opts): - """Encrypts and decrypts BSON values. - - This class is used by a driver to support explicit encryption and - decryption of individual fields in a BSON document. - - :Parameters: - - `callback`: A :class:`MongoCryptCallback`. - - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. - """ - self.callback = callback - if mongo_crypt_opts.schema_map is not None: - raise ValueError("mongo_crypt_opts.schema_map must be None") - self.mongocrypt = MongoCrypt(mongo_crypt_opts, callback) - - def create_data_key(self, kms_provider, master_key=None, - key_alt_names=None, key_material=None): - """Creates a data key used for explicit encryption. - - :Parameters: - - `kms_provider`: The KMS provider to use. Supported values are - "aws", "azure", "gcp", "kmip", and "local". - - `master_key`: See class:`DataKeyOpts`. - - `key_alt_names` (optional): An optional list of string alternate - names used to reference a key. If a key is created with alternate - names, then encryption may refer to the key by the unique - alternate name instead of by ``_id``. - - `key_material`: (optional) See class:`DataKeyOpts`. - - :Returns: - The _id of the created data key document. - """ - # CDRIVER-3275 each key_alt_name needs to be wrapped in a bson - # document. - encoded_names = [] - if key_alt_names is not None: - for name in key_alt_names: - encoded_names.append( - self.callback.bson_encode({'keyAltName': name})) - - if key_material is not None: - key_material = self.callback.bson_encode({'keyMaterial': key_material}) - - opts = DataKeyOpts(master_key, encoded_names, key_material) - with self.mongocrypt.data_key_context(kms_provider, opts) as ctx: - key = run_state_machine(ctx, self.callback) - return self.callback.insert_data_key(key) - - def rewrap_many_data_key(self, filter, provider=None, master_key=None): - """Decrypts and encrypts all matching data keys with a possibly new `master_key` value. - - :Parameters: - - `filter`: A document used to filter the data keys. - - `provider`: (optional) The name of a different kms provider. - - `master_key`: Optional document for the given provider. - - :Returns: - A binary document with the rewrap data. - """ - with self.mongocrypt.rewrap_many_data_key_context(filter, provider, master_key) as ctx: - return run_state_machine(ctx, self.callback) - - def encrypt(self, value, algorithm, key_id=None, key_alt_name=None, - query_type=None, contention_factor=None, range_opts=None, - is_expression=False): - """Encrypts a BSON value. - - Note that exactly one of ``key_id`` or ``key_alt_name`` must be - provided. - - :Parameters: - - `value` (bytes): The BSON value to encrypt. - - `algorithm` (string): The encryption algorithm to use. See - :class:`Algorithm` for some valid options. - - `key_id` (bytes): The bytes of the binary subtype 4 ``_id`` data - key. For example, ``uuid.bytes`` or ``bytes(bson_binary)``. - - `key_alt_name` (string): Identifies a key vault document by - 'keyAltName'. - - `query_type` (str): The query type to execute. - - `contention_factor` (int): The contention factor to use - when the algorithm is "Indexed". - - `range_opts` (bytes): Options for explicit encryption - with the "rangePreview" algorithm encoded as a BSON document. - - `is_expression` (boolean): True if this is an encryptExpression() - context. Defaults to False. - - :Returns: - The encrypted BSON value. - - .. versionchanged:: 1.3 - Added the `query_type` and `contention_factor` parameters. - .. versionchanged:: 1.5 - Added the `range_opts` and `is_expression` parameters. - """ - # CDRIVER-3275 key_alt_name needs to be wrapped in a bson document. - if key_alt_name is not None: - key_alt_name = self.callback.bson_encode( - {'keyAltName': key_alt_name}) - opts = ExplicitEncryptOpts( - algorithm, key_id, key_alt_name, query_type, contention_factor, - range_opts, is_expression) - with self.mongocrypt.explicit_encryption_context(value, opts) as ctx: - return run_state_machine(ctx, self.callback) - - def decrypt(self, value): - """Decrypts a BSON value. - - :Parameters: - - `value`: The encoded document to decrypt, which must be in the - form { "v" : encrypted BSON value }}. - - :Returns: - The decrypted BSON value. - """ - with self.mongocrypt.explicit_decryption_context(value) as ctx: - return run_state_machine(ctx, self.callback) - - def close(self): - """Cleanup resources.""" - self.mongocrypt.close() +from pymongocrypt.synchronous.explicit_encrypter import * diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/mongocrypt.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/mongocrypt.py index 8da865b..88dd19c 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/mongocrypt.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/mongocrypt.py @@ -12,158 +12,32 @@ # See the License for the specific language governing permissions and # limitations under the License. -import copy - - -from pymongocrypt.binary import (MongoCryptBinaryIn, - MongoCryptBinaryOut) -from pymongocrypt.binding import ffi, lib, _to_string -from pymongocrypt.compat import str_to_bytes, unicode_type -from pymongocrypt.credentials import _ask_for_kms_credentials +import platform +import sys + +from packaging.version import Version + +from pymongocrypt.asynchronous.state_machine import AsyncMongoCryptCallback +from pymongocrypt.binary import MongoCryptBinaryIn, MongoCryptBinaryOut +from pymongocrypt.binding import _to_string, ffi, lib +from pymongocrypt.compat import str_to_bytes +from pymongocrypt.crypto import ( + aes_256_cbc_decrypt, + aes_256_cbc_encrypt, + aes_256_ctr_decrypt, + aes_256_ctr_encrypt, + hmac_sha_256, + hmac_sha_512, + secure_random, + sha_256, + sign_rsaes_pkcs1_v1_5, +) from pymongocrypt.errors import MongoCryptError -from pymongocrypt.state_machine import MongoCryptCallback - -from pymongocrypt.crypto import (aes_256_cbc_encrypt, - aes_256_cbc_decrypt, - aes_256_ctr_decrypt, - aes_256_ctr_encrypt, - hmac_sha_256, - hmac_sha_512, - sha_256, - secure_random, - sign_rsaes_pkcs1_v1_5) - - -class MongoCryptOptions(object): - def __init__(self, kms_providers, schema_map=None, encrypted_fields_map=None, - bypass_query_analysis=False, crypt_shared_lib_path=None, - crypt_shared_lib_required=False, bypass_encryption=False): - """Options for :class:`MongoCrypt`. - - :Parameters: - - `kms_providers`: Map of KMS provider options. The kms_providers - map values differ by provider: - - `aws`: Map with "accessKeyId" and "secretAccessKey" as strings, - and optionally a "sessionToken" for temporary credentials. - - `azure`: Map with "clientId" and "clientSecret" as strings. - - `gcp`: Map with "email" as a string and "privateKey" as - a byte array or a base64-encoded string. - - `kmip`: Map with "endpoint" as a string. - - `local`: Map with "key" as a 96-byte array or the equivalent - base64-encoded string. - - `schema_map`: Optional map of collection namespace ("db.coll") to - JSON Schema. By default, a collection's JSONSchema is periodically - polled with the listCollections command. But a JSONSchema may be - specified locally with the schemaMap option. - - Supplying a `schema_map` provides more security than relying on - JSON Schemas obtained from the server. It protects against a - malicious server advertising a false JSON Schema, which could trick - the client into sending unencrypted data that should be encrypted. - - Schemas supplied in the schemaMap only apply to configuring - automatic encryption for client side encryption. Other validation - rules in the JSON schema will not be enforced by the driver and - will result in an error. - - `encrypted_fields_map`: Optional map encoded to BSON `bytes`. - - `bypass_query_analysis`: If ``True``, disable automatic analysis of - outgoing commands. Set `bypass_query_analysis` to use explicit - encryption on indexed fields without the MongoDB Enterprise Advanced - licensed crypt_shared library. - - `crypt_shared_lib_path`: Optional string path to the crypt_shared - library. - - `crypt_shared_lib_required`: Whether to require a crypt_shared - library. - - `bypass_encryption`: Whether to bypass encryption. - - .. versionadded:: 1.3 - ``crypt_shared_lib_path``, ``crypt_shared_lib_path``, - ``bypass_encryption`` parameters. - - .. versionadded:: 1.1 - Support for "azure" and "gcp" kms_providers. - Support for temporary AWS credentials via "sessionToken". - - .. versionchanged:: 1.1 - For kmsProvider "local", the "key" field can now be specified - as either a 96-byte array or the equivalent base64-encoded string. - """ - if not isinstance(kms_providers, dict): - raise ValueError('kms_providers must be a dict') - if not kms_providers: - raise ValueError('at least one KMS provider must be configured') - - if 'aws' in kms_providers: - aws = kms_providers["aws"] - if not isinstance(aws, dict): - raise ValueError("kms_providers['aws'] must be a dict") - if len(aws): - if "accessKeyId" not in aws or "secretAccessKey" not in aws: - raise ValueError("kms_providers['aws'] must contain " - "'accessKeyId' and 'secretAccessKey'") - - if 'azure' in kms_providers: - azure = kms_providers["azure"] - if not isinstance(azure, dict): - raise ValueError("kms_providers['azure'] must be a dict") - if len(azure): - if 'clientId' not in azure or 'clientSecret' not in azure: - raise ValueError("kms_providers['azure'] must contain " - "'clientId' and 'clientSecret'") - - if 'gcp' in kms_providers: - gcp = kms_providers['gcp'] - if not isinstance(gcp, dict): - raise ValueError("kms_providers['gcp'] must be a dict") - if len(gcp): - if 'email' not in gcp or 'privateKey' not in gcp: - raise ValueError("kms_providers['gcp'] must contain " - "'email' and 'privateKey'") - if not isinstance(kms_providers['gcp']['privateKey'], - (bytes, unicode_type)): - raise TypeError("kms_providers['gcp']['privateKey'] must " - "be an instance of bytes or str") - - if 'kmip' in kms_providers: - kmip = kms_providers['kmip'] - if not isinstance(kmip, dict): - raise ValueError("kms_providers['kmip'] must be a dict") - if 'endpoint' not in kmip: - raise ValueError("kms_providers['kmip'] must contain " - "'endpoint'") - if not isinstance(kms_providers['kmip']['endpoint'], - (str, unicode_type)): - raise TypeError("kms_providers['kmip']['endpoint'] must " - "be an instance of str") - - if 'local' in kms_providers: - local = kms_providers['local'] - if not isinstance(local, dict): - raise ValueError("kms_providers['local'] must be a dict") - if 'key' not in local: - raise ValueError("kms_providers['local'] must contain 'key'") - if not isinstance(kms_providers['local']['key'], - (bytes, unicode_type)): - raise TypeError("kms_providers['local']['key'] must be an " - "instance of bytes or str") - - if schema_map is not None and not isinstance(schema_map, bytes): - raise TypeError("schema_map must be bytes or None") - - if encrypted_fields_map is not None and not isinstance(encrypted_fields_map, bytes): - raise TypeError("encrypted_fields_map must be bytes or None") - - self.kms_providers = kms_providers - self.schema_map = schema_map - self.encrypted_fields_map = encrypted_fields_map - self.bypass_query_analysis = bypass_query_analysis - self.crypt_shared_lib_path = crypt_shared_lib_path - self.crypt_shared_lib_required = crypt_shared_lib_required - self.bypass_encryption = bypass_encryption - +from pymongocrypt.options import MongoCryptOptions +from pymongocrypt.synchronous.state_machine import MongoCryptCallback -class MongoCrypt(object): +class MongoCrypt: def __init__(self, options, callback): """Abstracts libmongocrypt's mongocrypt_t type. @@ -178,8 +52,10 @@ def __init__(self, options, callback): if not isinstance(options, MongoCryptOptions): raise TypeError("options must be a MongoCryptOptions") - if not isinstance(callback, MongoCryptCallback): - raise TypeError("callback must be a MongoCryptCallback") + if not isinstance(callback, (AsyncMongoCryptCallback, MongoCryptCallback)): + raise TypeError( + "callback must be a MongoCryptCallback or AsyncMongoCryptCallback" + ) self.__crypt = lib.mongocrypt_new() if self.__crypt == ffi.NULL: @@ -195,63 +71,96 @@ def __init__(self, options, callback): def __init(self): """Internal init helper.""" kms_providers = self.__opts.kms_providers - with MongoCryptBinaryIn( - self.__callback.bson_encode(kms_providers)) as kmsopt: - if not lib.mongocrypt_setopt_kms_providers( - self.__crypt, kmsopt.bin): + with MongoCryptBinaryIn(self.__callback.bson_encode(kms_providers)) as kmsopt: + if not lib.mongocrypt_setopt_kms_providers(self.__crypt, kmsopt.bin): self.__raise_from_status() schema_map = self.__opts.schema_map if schema_map is not None: with MongoCryptBinaryIn(schema_map) as binary_schema_map: if not lib.mongocrypt_setopt_schema_map( - self.__crypt, binary_schema_map.bin): + self.__crypt, binary_schema_map.bin + ): self.__raise_from_status() encrypted_fields_map = self.__opts.encrypted_fields_map if encrypted_fields_map is not None: - with MongoCryptBinaryIn(encrypted_fields_map) as binary_encrypted_fields_map: + with MongoCryptBinaryIn( + encrypted_fields_map + ) as binary_encrypted_fields_map: if not lib.mongocrypt_setopt_encrypted_field_config_map( - self.__crypt, binary_encrypted_fields_map.bin): + self.__crypt, binary_encrypted_fields_map.bin + ): self.__raise_from_status() if self.__opts.bypass_query_analysis: lib.mongocrypt_setopt_bypass_query_analysis(self.__crypt) - if not lib.mongocrypt_setopt_crypto_hooks( - self.__crypt, aes_256_cbc_encrypt, aes_256_cbc_decrypt, - secure_random, hmac_sha_512, hmac_sha_256, sha_256, ffi.NULL): - self.__raise_from_status() + # Prefer using the native crypto binding when we know it's available. + try: + crypto_available = lib.mongocrypt_is_crypto_available() + except AttributeError: + # libmongocrypt < 1.9 + crypto_available = False + + if not crypto_available: + if not lib.mongocrypt_setopt_crypto_hooks( + self.__crypt, + aes_256_cbc_encrypt, + aes_256_cbc_decrypt, + secure_random, + hmac_sha_512, + hmac_sha_256, + sha_256, + ffi.NULL, + ): + self.__raise_from_status() - if not lib.mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( - self.__crypt, sign_rsaes_pkcs1_v1_5, ffi.NULL): - self.__raise_from_status() + if not lib.mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5( + self.__crypt, sign_rsaes_pkcs1_v1_5, ffi.NULL + ): + self.__raise_from_status() - if not lib.mongocrypt_setopt_aes_256_ctr( - self.__crypt, aes_256_ctr_encrypt, aes_256_ctr_decrypt, ffi.NULL): - self.__raise_from_status() + if not lib.mongocrypt_setopt_aes_256_ctr( + self.__crypt, aes_256_ctr_encrypt, aes_256_ctr_decrypt, ffi.NULL + ): + self.__raise_from_status() + elif sys.platform == "darwin" and Version(platform.mac_ver()[0]) < Version( + "10.15" + ): + # MONGOCRYPT-440 libmongocrypt does not support AES-CTR on macOS < 10.15. + if not lib.mongocrypt_setopt_aes_256_ctr( + self.__crypt, aes_256_ctr_encrypt, aes_256_ctr_decrypt, ffi.NULL + ): + self.__raise_from_status() if self.__opts.crypt_shared_lib_path is not None: lib.mongocrypt_setopt_set_crypt_shared_lib_path_override( - self.__crypt, self.__opts.crypt_shared_lib_path.encode("utf-8")) + self.__crypt, self.__opts.crypt_shared_lib_path.encode("utf-8") + ) if not self.__opts.bypass_encryption: - lib.mongocrypt_setopt_append_crypt_shared_lib_search_path(self.__crypt, b"$SYSTEM") - on_demand_aws = 'aws' in kms_providers and not len(kms_providers['aws']) - on_demand_gcp = 'gcp' in kms_providers and not len(kms_providers['gcp']) - on_demand_azure = 'azure' in kms_providers and not len(kms_providers['azure']) + lib.mongocrypt_setopt_append_crypt_shared_lib_search_path( + self.__crypt, b"$SYSTEM" + ) + on_demand_aws = "aws" in kms_providers and not len(kms_providers["aws"]) + on_demand_gcp = "gcp" in kms_providers and not len(kms_providers["gcp"]) + on_demand_azure = "azure" in kms_providers and not len(kms_providers["azure"]) if any([on_demand_aws, on_demand_gcp, on_demand_azure]): lib.mongocrypt_setopt_use_need_kms_credentials_state(self.__crypt) if not lib.mongocrypt_init(self.__crypt): self.__raise_from_status() - if self.__opts.crypt_shared_lib_required and self.crypt_shared_lib_version is None: + if ( + self.__opts.crypt_shared_lib_required + and self.crypt_shared_lib_version is None + ): raise MongoCryptError( "crypt_shared_lib_required=True but the crypt_shared library could not be loaded " - "from crypt_shared_lib_path={}".format( - self.__opts.crypt_shared_lib_path) + - " or the operating system's dynamic library search path") + f"from crypt_shared_lib_path={self.__opts.crypt_shared_lib_path}" + + " or the operating system's dynamic library search path" + ) def __raise_from_status(self): status = lib.mongocrypt_status_new() @@ -300,7 +209,9 @@ def encryption_context(self, database, command): :Returns: A :class:`EncryptionContext`. """ - return EncryptionContext(self._create_context(), self.__opts.kms_providers, database, command) + return EncryptionContext( + self._create_context(), self.__opts.kms_providers, database, command + ) def decryption_context(self, command): """Creates a context to use for decryption. @@ -311,7 +222,9 @@ def decryption_context(self, command): :Returns: A :class:`DecryptionContext`. """ - return DecryptionContext(self._create_context(), self.__opts.kms_providers, command) + return DecryptionContext( + self._create_context(), self.__opts.kms_providers, command + ) def explicit_encryption_context(self, value, opts): """Creates a context to use for explicit encryption. @@ -325,7 +238,8 @@ def explicit_encryption_context(self, value, opts): A :class:`ExplicitEncryptionContext`. """ return ExplicitEncryptionContext( - self._create_context(), self.__opts.kms_providers, value, opts) + self._create_context(), self.__opts.kms_providers, value, opts + ) def explicit_decryption_context(self, value): """Creates a context to use for explicit decryption. @@ -337,8 +251,9 @@ def explicit_decryption_context(self, value): :Returns: A :class:`ExplicitDecryptionContext`. """ - return ExplicitDecryptionContext(self._create_context(), - self.__opts.kms_providers, value) + return ExplicitDecryptionContext( + self._create_context(), self.__opts.kms_providers, value + ) def data_key_context(self, kms_provider, opts=None): """Creates a context to use for key generation. @@ -350,8 +265,13 @@ def data_key_context(self, kms_provider, opts=None): :Returns: A :class:`DataKeyContext`. """ - return DataKeyContext(self._create_context(), self.__opts.kms_providers, kms_provider, opts, - self.__callback) + return DataKeyContext( + self._create_context(), + self.__opts.kms_providers, + kms_provider, + opts, + self.__callback, + ) def rewrap_many_data_key_context(self, filter, provider, master_key): """Creates a context to use for rewrapping many data keys. @@ -367,11 +287,18 @@ def rewrap_many_data_key_context(self, filter, provider, master_key): :Returns: A :class:`RewrapManyDataKeyContext`. """ - return RewrapManyDataKeyContext(self._create_context(), self.__opts.kms_providers, filter, provider, master_key, self.__callback) + return RewrapManyDataKeyContext( + self._create_context(), + self.__opts.kms_providers, + filter, + provider, + master_key, + self.__callback, + ) -class MongoCryptContext(object): - __slots__ = ("__ctx", "__kms_providers") +class MongoCryptContext: + __slots__ = ("__ctx", "kms_providers") def __init__(self, ctx, kms_providers): """Abstracts libmongocrypt's mongocrypt_ctx_t type. @@ -382,7 +309,7 @@ def __init__(self, ctx, kms_providers): - `kms_providers`: The KMS provider map. """ self.__ctx = ctx - self.__kms_providers = kms_providers + self.kms_providers = kms_providers def _close(self): """Cleanup resources.""" @@ -433,10 +360,6 @@ def complete_mongo_operation(self): if not lib.mongocrypt_ctx_mongo_done(self.__ctx): self._raise_from_status() - def ask_for_kms_credentials(self): - """Get on-demand kms credentials""" - return _ask_for_kms_credentials(self.__kms_providers) - def provide_kms_providers(self, providers): """Provide a map of KMS providers.""" with MongoCryptBinaryIn(providers) as binary: @@ -476,13 +399,14 @@ def __init__(self, ctx, kms_providers, database, command): - `database`: Optional, the name of the database. - `command`: The BSON command to encrypt. """ - super(EncryptionContext, self).__init__(ctx, kms_providers) + super().__init__(ctx, kms_providers) self.database = database try: with MongoCryptBinaryIn(command) as binary: database = str_to_bytes(database) if not lib.mongocrypt_ctx_encrypt_init( - ctx, database, len(database), binary.bin): + ctx, database, len(database), binary.bin + ): self._raise_from_status() except Exception: # Destroy the context on error. @@ -502,7 +426,7 @@ def __init__(self, ctx, kms_providers, command): - `kms_providers`: The KMS provider map. - `command`: The encoded BSON command to decrypt. """ - super(DecryptionContext, self).__init__(ctx, kms_providers) + super().__init__(ctx, kms_providers) try: with MongoCryptBinaryIn(command) as binary: if not lib.mongocrypt_ctx_decrypt_init(ctx, binary.bin): @@ -527,7 +451,7 @@ def __init__(self, ctx, kms_providers, value, opts): form { "v" : BSON value to encrypt }}. - `opts`: A :class:`ExplicitEncryptOpts`. """ - super(ExplicitEncryptionContext, self).__init__(ctx, kms_providers) + super().__init__(ctx, kms_providers) try: algorithm = str_to_bytes(opts.algorithm) if not lib.mongocrypt_ctx_setopt_algorithm(ctx, algorithm, -1): @@ -549,17 +473,23 @@ def __init__(self, ctx, kms_providers, value, opts): self._raise_from_status() if opts.contention_factor is not None: - if not lib.mongocrypt_ctx_setopt_contention_factor(ctx, opts.contention_factor): + if not lib.mongocrypt_ctx_setopt_contention_factor( + ctx, opts.contention_factor + ): self._raise_from_status() if opts.range_opts is not None: with MongoCryptBinaryIn(opts.range_opts) as range_opts: - if not lib.mongocrypt_ctx_setopt_algorithm_range(ctx, range_opts.bin): + if not lib.mongocrypt_ctx_setopt_algorithm_range( + ctx, range_opts.bin + ): self._raise_from_status() with MongoCryptBinaryIn(value) as binary: if opts.is_expression: - if not lib.mongocrypt_ctx_explicit_encrypt_expression_init(ctx, binary.bin): + if not lib.mongocrypt_ctx_explicit_encrypt_expression_init( + ctx, binary.bin + ): self._raise_from_status() else: if not lib.mongocrypt_ctx_explicit_encrypt_init(ctx, binary.bin): @@ -582,12 +512,11 @@ def __init__(self, ctx, kms_providers, value): - `kms_providers`: The KMS provider map. - `value`: The encoded BSON value to decrypt. """ - super(ExplicitDecryptionContext, self).__init__(ctx, kms_providers) + super().__init__(ctx, kms_providers) try: with MongoCryptBinaryIn(value) as binary: - if not lib.mongocrypt_ctx_explicit_decrypt_init(ctx, - binary.bin): + if not lib.mongocrypt_ctx_explicit_decrypt_init(ctx, binary.bin): self._raise_from_status() except Exception: # Destroy the context on error. @@ -609,60 +538,61 @@ def __init__(self, ctx, kms_providers, kms_provider, opts, callback): - `opts`: An optional class:`DataKeyOpts`. - `callback`: A :class:`MongoCryptCallback`. """ - super(DataKeyContext, self).__init__(ctx, kms_providers) + super().__init__(ctx, kms_providers) try: - if kms_provider not in ['aws', 'gcp', 'azure', 'kmip', 'local']: - raise ValueError('unknown kms_provider: %s' % (kms_provider,)) + if kms_provider not in kms_providers: + raise ValueError(f"unknown kms_provider: {kms_provider}") + # Account for provider names like "local:myname". + provider_type = kms_provider.split(":")[0] if opts is None or opts.master_key is None: - if kms_provider in ['kmip', 'local']: + if provider_type in ["kmip", "local"]: master_key = {} else: raise ValueError( - 'master_key is required for kms_provider: "%s"' % ( - kms_provider,)) + f"master_key is required for kms_provider: {kms_provider!r}" + ) else: master_key = opts.master_key.copy() - if kms_provider == 'aws': - if ('region' not in master_key or - 'key' not in master_key): + if provider_type == "aws": + if "region" not in master_key or "key" not in master_key: raise ValueError( 'master_key must include "region" and "key" for ' - 'kms_provider: "aws"') - elif kms_provider == 'azure': - if ('keyName' not in master_key or - 'keyVaultEndpoint' not in master_key): + f"kms_provider: {kms_provider!r}" + ) + elif provider_type == "azure": + if "keyName" not in master_key or "keyVaultEndpoint" not in master_key: raise ValueError( 'master key must include "keyName" and ' - '"keyVaultEndpoint" for kms_provider: "azure"') - elif kms_provider == 'gcp': - if ('projectId' not in master_key or - 'location' not in master_key or - 'keyRing' not in master_key or - 'keyName' not in master_key): + f'"keyVaultEndpoint" for kms_provider: {kms_provider!r}' + ) + elif provider_type == "gcp": + if ( + "projectId" not in master_key + or "location" not in master_key + or "keyRing" not in master_key + or "keyName" not in master_key + ): raise ValueError( 'master key must include "projectId", "location",' - '"keyRing", and "keyName" for kms_provider: "gcp"') + f'"keyRing", and "keyName" for kms_provider: {kms_provider!r}' + ) - master_key['provider'] = kms_provider - with MongoCryptBinaryIn( - callback.bson_encode(master_key)) as mkey: - if not lib.mongocrypt_ctx_setopt_key_encryption_key( - ctx, mkey.bin): + master_key["provider"] = kms_provider + with MongoCryptBinaryIn(callback.bson_encode(master_key)) as mkey: + if not lib.mongocrypt_ctx_setopt_key_encryption_key(ctx, mkey.bin): self._raise_from_status() if opts.key_alt_names: for key_alt_name in opts.key_alt_names: with MongoCryptBinaryIn(key_alt_name) as binary: - if not lib.mongocrypt_ctx_setopt_key_alt_name( - ctx, binary.bin): + if not lib.mongocrypt_ctx_setopt_key_alt_name(ctx, binary.bin): self._raise_from_status() if opts.key_material: with MongoCryptBinaryIn(opts.key_material) as binary: - if not lib.mongocrypt_ctx_setopt_key_material( - ctx, binary.bin): + if not lib.mongocrypt_ctx_setopt_key_material(ctx, binary.bin): self._raise_from_status() if not lib.mongocrypt_ctx_datakey_init(ctx): @@ -673,7 +603,7 @@ def __init__(self, ctx, kms_providers, kms_provider, opts, callback): raise -class MongoCryptKmsContext(object): +class MongoCryptKmsContext: __slots__ = ("__ctx",) def __init__(self, ctx): @@ -727,8 +657,7 @@ def kms_provider(self): .. versionadded:: 1.2 """ - return _to_string( - lib.mongocrypt_kms_ctx_get_kms_provider(self.__ctx, ffi.NULL)) + return _to_string(lib.mongocrypt_kms_ctx_get_kms_provider(self.__ctx, ffi.NULL)) def feed(self, data): """Feed bytes from the HTTP response. @@ -754,8 +683,7 @@ def __raise_from_status(self): class RewrapManyDataKeyContext(MongoCryptContext): __slots__ = () - def __init__(self, ctx, kms_providers, filter, provider, master_key, - callback): + def __init__(self, ctx, kms_providers, filter, provider, master_key, callback): """Abstracts libmongocrypt's mongocrypt_ctx_t type. :Parameters: @@ -767,7 +695,7 @@ def __init__(self, ctx, kms_providers, filter, provider, master_key, - `master_key`: Optional document for the given provider. - `callback`: A :class:`MongoCryptCallback`. """ - super(RewrapManyDataKeyContext, self).__init__(ctx, kms_providers) + super().__init__(ctx, kms_providers) key_encryption_key_bson = None if provider is not None: data = dict(provider=provider) @@ -778,7 +706,9 @@ def __init__(self, ctx, kms_providers, filter, provider, master_key, try: if key_encryption_key_bson: with MongoCryptBinaryIn(key_encryption_key_bson) as binary: - if not lib.mongocrypt_ctx_setopt_key_encryption_key(ctx, binary.bin): + if not lib.mongocrypt_ctx_setopt_key_encryption_key( + ctx, binary.bin + ): self._raise_from_status() filter_bson = callback.bson_encode(filter) diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/options.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/options.py new file mode 100644 index 0000000..6b905d4 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/options.py @@ -0,0 +1,265 @@ +from pymongocrypt.compat import unicode_type + + +class MongoCryptOptions: + def __init__( + self, + kms_providers, + schema_map=None, + encrypted_fields_map=None, + bypass_query_analysis=False, + crypt_shared_lib_path=None, + crypt_shared_lib_required=False, + bypass_encryption=False, + ): + """Options for :class:`MongoCrypt`. + + :Parameters: + - `kms_providers`: Map of KMS provider options. The kms_providers + map values differ by provider: + - `aws`: Map with "accessKeyId" and "secretAccessKey" as strings, + and optionally a "sessionToken" for temporary credentials. + - `azure`: Map with "clientId" and "clientSecret" as strings. + - `gcp`: Map with "email" as a string and "privateKey" as + a byte array or a base64-encoded string. + - `kmip`: Map with "endpoint" as a string. + - `local`: Map with "key" as a 96-byte array or the equivalent + base64-encoded string. + + KMS providers may be specified with an optional name suffix + separated by a colon, for example "kmip:name". Named KMS providers + do not support automatic credential lookup. + - `schema_map`: Optional map of collection namespace ("db.coll") to + JSON Schema. By default, a collection's JSONSchema is periodically + polled with the listCollections command. But a JSONSchema may be + specified locally with the schemaMap option. + + Supplying a `schema_map` provides more security than relying on + JSON Schemas obtained from the server. It protects against a + malicious server advertising a false JSON Schema, which could trick + the client into sending unencrypted data that should be encrypted. + + Schemas supplied in the schemaMap only apply to configuring + automatic encryption for client side encryption. Other validation + rules in the JSON schema will not be enforced by the driver and + will result in an error. + - `encrypted_fields_map`: Optional map encoded to BSON `bytes`. + - `bypass_query_analysis`: If ``True``, disable automatic analysis of + outgoing commands. Set `bypass_query_analysis` to use explicit + encryption on indexed fields without the MongoDB Enterprise Advanced + licensed crypt_shared library. + - `crypt_shared_lib_path`: Optional string path to the crypt_shared + library. + - `crypt_shared_lib_required`: Whether to require a crypt_shared + library. + - `bypass_encryption`: Whether to bypass encryption. + + .. versionremoved:: 1.11 + Removed the ``enable_range_v2`` parameter. + + .. versionadded:: 1.10 + Added the ``enable_range_v2`` parameter. + + .. versionadded:: 1.3 + Added the ``crypt_shared_lib_path``, ``crypt_shared_lib_path``, and + ``bypass_encryption`` parameters. + + .. versionadded:: 1.1 + Support for "azure" and "gcp" kms_providers. + Support for temporary AWS credentials via "sessionToken". + + .. versionchanged:: 1.1 + For kmsProvider "local", the "key" field can now be specified + as either a 96-byte array or the equivalent base64-encoded string. + """ + if not isinstance(kms_providers, dict): + raise ValueError("kms_providers must be a dict") + if not kms_providers: + raise ValueError("at least one KMS provider must be configured") + + for name, provider in kms_providers.items(): + # Account for provider names like "local:myname". + provider_type = name.split(":")[0] + if provider_type in ("aws", "gcp", "azure", "kmip", "local"): + if not isinstance(provider, dict): + raise ValueError(f"kms_providers[{name!r}] must be a dict") + if provider_type == "aws": + if len(provider): + if ( + "accessKeyId" not in provider + or "secretAccessKey" not in provider + ): + raise ValueError( + f"kms_providers[{name!r}] must contain " + "'accessKeyId' and 'secretAccessKey'" + ) + elif provider_type == "azure": + if len(provider): + if "clientId" not in provider or "clientSecret" not in provider: + raise ValueError( + f"kms_providers[{name!r}] must contain " + "'clientId' and 'clientSecret'" + ) + elif provider_type == "gcp": + if len(provider): + if "email" not in provider or "privateKey" not in provider: + raise ValueError( + f"kms_providers[{name!r}] must contain " + "'email' and 'privateKey'" + ) + if not isinstance(provider["privateKey"], (bytes, unicode_type)): + raise TypeError( + f"kms_providers[{name!r}]['privateKey'] must " + "be an instance of bytes or str" + ) + elif provider_type == "kmip": + if "endpoint" not in provider: + raise ValueError(f"kms_providers[{name!r}] must contain 'endpoint'") + if not isinstance(provider["endpoint"], (str, unicode_type)): + raise TypeError( + f"kms_providers[{name!r}]['endpoint'] must " + "be an instance of str" + ) + elif provider_type == "local": + if "key" not in provider: + raise ValueError(f"kms_providers[{name!r}] must contain 'key'") + if not isinstance(provider["key"], (bytes, unicode_type)): + raise TypeError( + f"kms_providers[{name!r}]['key'] must be an " + "instance of bytes or str" + ) + + if schema_map is not None and not isinstance(schema_map, bytes): + raise TypeError("schema_map must be bytes or None") + + if encrypted_fields_map is not None and not isinstance( + encrypted_fields_map, bytes + ): + raise TypeError("encrypted_fields_map must be bytes or None") + + self.kms_providers = kms_providers + self.schema_map = schema_map + self.encrypted_fields_map = encrypted_fields_map + self.bypass_query_analysis = bypass_query_analysis + self.crypt_shared_lib_path = crypt_shared_lib_path + self.crypt_shared_lib_required = crypt_shared_lib_required + self.bypass_encryption = bypass_encryption + + +class ExplicitEncryptOpts: + def __init__( + self, + algorithm, + key_id=None, + key_alt_name=None, + query_type=None, + contention_factor=None, + range_opts=None, + is_expression=False, + ): + """Options for explicit encryption. + + :Parameters: + - `algorithm` (str): The algorithm to use. + - `key_id`: The data key _id. + - `key_alt_name` (bytes): Identifies a key vault document by + 'keyAltName'. Must be BSON encoded document in the form: + { "keyAltName" : (BSON UTF8 value) } + - `query_type` (str): The query type to execute. + - `contention_factor` (int): The contention factor to use + when the algorithm is "Indexed". + - `range_opts` (bytes): Options for explicit encryption + with the "range" algorithm encoded as a BSON document. + - `is_expression` (boolean): True if this is an encryptExpression() + context. Defaults to False. + + .. versionchanged:: 1.3 + Added the `query_type` and `contention_factor` parameters. + .. versionchanged:: 1.5 + Added the `range_opts` and `is_expression` parameters. + """ + self.algorithm = algorithm + self.key_id = key_id + self.key_alt_name = key_alt_name + if query_type is not None: + if not isinstance(query_type, str): + raise TypeError( + f"query_type must be str or None, not: {type(query_type)}" + ) + self.query_type = query_type + if contention_factor is not None and not isinstance(contention_factor, int): + raise TypeError( + f"contention_factor must be an int or None, not: {type(contention_factor)}" + ) + self.contention_factor = contention_factor + if range_opts is not None and not isinstance(range_opts, bytes): + raise TypeError( + f"range_opts must be an bytes or None, not: {type(range_opts)}" + ) + self.range_opts = range_opts + self.is_expression = is_expression + + +class DataKeyOpts: + def __init__(self, master_key=None, key_alt_names=None, key_material=None): + """Options for creating encryption keys. + + :Parameters: + - `master_key`: Identifies a KMS-specific key used to encrypt the + new data key. If the kmsProvider is "local" the `master_key` is + not applicable and may be omitted. + + If the `kms_provider` is "aws" it is required and has the + following fields:: + + - `region` (string): Required. The AWS region, e.g. "us-east-1". + - `key` (string): Required. The Amazon Resource Name (ARN) to + the AWS customer. + - `endpoint` (string): Optional. An alternate host to send KMS + requests to. May include port number, e.g. + "kms.us-east-1.amazonaws.com:443". + + If the `kms_provider` is "azure" it is required and has the + following fields:: + + - `keyVaultEndpoint` (string): Required. Host with optional + port, e.g. "example.vault.azure.net". + - `keyName` (string): Required. Key name in the key vault. + - `keyVersion` (string): Optional. Version of the key to use. + + If the `kms_provider` is "gcp" it is required and has the + following fields:: + + - `projectId` (string): Required. The Google cloud project ID. + - `location` (string): Required. The GCP location, e.g. "us-east1". + - `keyRing` (string): Required. Name of the key ring that contains + the key to use. + - `keyName` (string): Required. Name of the key to use. + - `keyVersion` (string): Optional. Version of the key to use. + - `endpoint` (string): Optional. Host with optional port. + Defaults to "cloudkms.googleapis.com". + + If the `kms_provider` is "kmip" it is optional and has the + following fields:: + + - `keyId` (string): Optional. `keyId` is the KMIP Unique + Identifier to a 96 byte KMIP Secret Data managed object. If + keyId is omitted, the driver creates a random 96 byte KMIP + Secret Data managed object. + - `endpoint` (string): Optional. Host with optional + port, e.g. "example.vault.azure.net:". + + - `key_alt_names`: An optional list of bytes suitable to be passed to + mongocrypt_ctx_setopt_key_alt_name. Each element must be BSON + encoded document in the form: { "keyAltName" : (BSON UTF8 value) } + + - `key_material`: An optional binary value of 96 bytes to use as + custom key material for the data key being created. If + ``key_material`` is given, the custom key material is used for + encrypting and decrypting data. Otherwise, the key material for the + new data key is generated from a cryptographically secure random + device. + """ + self.master_key = master_key + self.key_alt_names = key_alt_names + self.key_material = key_material diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/state_machine.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/state_machine.py index 555896e..f2ae052 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/state_machine.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/state_machine.py @@ -12,145 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from abc import abstractmethod +# Alias file for import compatibility -from pymongocrypt.binding import lib -from pymongocrypt.compat import ABC -from pymongocrypt.errors import MongoCryptError - - -class MongoCryptCallback(ABC): - """Callback ABC to perform I/O on behalf of libbmongocrypt.""" - - @abstractmethod - def kms_request(self, kms_context): - """Complete a KMS request. - - :Parameters: - - `kms_context`: A :class:`MongoCryptKmsContext`. - - :Returns: - None - """ - pass - - @abstractmethod - def collection_info(self, database, filter): - """Get the collection info for a namespace. - - The returned collection info is passed to libmongocrypt which reads - the JSON schema. - - :Parameters: - - `database`: The database on which to run listCollections. - - `filter`: The filter to pass to listCollections. - - :Returns: - The first document from the listCollections command response as BSON. - """ - pass - - @abstractmethod - def mark_command(self, database, cmd): - """Mark a command for encryption. - - :Parameters: - - `database`: The database on which to run this command. - - `cmd`: The BSON command to run. - - :Returns: - The marked command response from mongocryptd. - """ - pass - - @abstractmethod - def fetch_keys(self, filter): - """Yields one or more keys from the key vault. - - :Parameters: - - `filter`: The filter to pass to find. - - :Returns: - A generator which yields the requested keys from the key vault. - """ - pass - - @abstractmethod - def insert_data_key(self, data_key): - """Insert a data key into the key vault. - - :Parameters: - - `data_key`: The data key document to insert. - - :Returns: - The _id of the inserted data key document. - """ - pass - - @abstractmethod - def bson_encode(self, doc): - """Encode a document to BSON. - - A document can be any mapping type (like :class:`dict`). - - :Parameters: - - `doc`: mapping type representing a document - - :Returns: - The encoded BSON bytes. - """ - pass - - @abstractmethod - def close(self): - """Release resources.""" - pass - - -def run_state_machine(ctx, callback): - """Run the libmongocrypt state machine until completion. - - :Parameters: - - `ctx`: A :class:`MongoCryptContext`. - - `callback`: A :class:`MongoCryptCallback`. - - :Returns: - The completed libmongocrypt operation. - """ - while True: - state = ctx.state - # Check for terminal states first. - if state == lib.MONGOCRYPT_CTX_ERROR: - ctx._raise_from_status() - elif state == lib.MONGOCRYPT_CTX_READY: - return ctx.finish() - elif state == lib.MONGOCRYPT_CTX_DONE: - return None - - if state == lib.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: - list_colls_filter = ctx.mongo_operation() - coll_info = callback.collection_info( - ctx.database, list_colls_filter) - if coll_info: - ctx.add_mongo_operation_result(coll_info) - ctx.complete_mongo_operation() - elif state == lib.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: - mongocryptd_cmd = ctx.mongo_operation() - result = callback.mark_command(ctx.database, mongocryptd_cmd) - ctx.add_mongo_operation_result(result) - ctx.complete_mongo_operation() - elif state == lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS: - key_filter = ctx.mongo_operation() - for key in callback.fetch_keys(key_filter): - ctx.add_mongo_operation_result(key) - ctx.complete_mongo_operation() - elif state == lib.MONGOCRYPT_CTX_NEED_KMS: - for kms_ctx in ctx.kms_contexts(): - with kms_ctx: - callback.kms_request(kms_ctx) - ctx.complete_kms() - elif state == lib.MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: - creds = ctx.ask_for_kms_credentials() - ctx.provide_kms_providers(callback.bson_encode(creds)) - else: - raise MongoCryptError('unknown state: %r' % (state,)) +from pymongocrypt.synchronous.state_machine import * diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/auto_encrypter.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/auto_encrypter.py new file mode 100644 index 0000000..4fc3f10 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/auto_encrypter.py @@ -0,0 +1,61 @@ +# Copyright 2024-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. + +from pymongocrypt.mongocrypt import MongoCrypt +from pymongocrypt.synchronous.state_machine import run_state_machine + + +class AutoEncrypter: + def __init__(self, callback, mongo_crypt_opts): + """Encrypts and decrypts MongoDB commands. + + This class is used by a driver to support automatic encryption and + decryption of MongoDB commands. + + :Parameters: + - `callback`: A :class:`MongoCryptCallback`. + - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. + """ + self.callback = callback + self.mongocrypt = MongoCrypt(mongo_crypt_opts, callback) + + def encrypt(self, database, cmd): + """Encrypt a MongoDB command. + + :Parameters: + - `database`: The database for this command. + - `cmd`: A MongoDB command as BSON. + + :Returns: + The encrypted command. + """ + with self.mongocrypt.encryption_context(database, cmd) as ctx: + return run_state_machine(ctx, self.callback) + + def decrypt(self, response): + """Decrypt a MongoDB command response. + + :Parameters: + - `response`: A MongoDB command response as BSON. + + :Returns: + The decrypted command response. + """ + with self.mongocrypt.decryption_context(response) as ctx: + return run_state_machine(ctx, self.callback) + + def close(self): + """Cleanup resources.""" + self.mongocrypt.close() + self.callback.close() diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/credentials.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/credentials.py new file mode 100644 index 0000000..9090dae --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/credentials.py @@ -0,0 +1,156 @@ +# Copyright 2024-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. +import os +from collections import namedtuple +from datetime import datetime, timedelta, timezone + +try: + from pymongo_auth_aws.auth import aws_temp_credentials + + _HAVE_AUTH_AWS = True +except ImportError: + _HAVE_AUTH_AWS = False + +import httpx + +from pymongocrypt.errors import MongoCryptError + +_azure_creds = namedtuple("_azure_creds", ["access_token", "expires_utc"]) +_azure_creds_cache = None + + +def _get_gcp_credentials(): + """Get on-demand GCP credentials""" + metadata_host = os.getenv("GCE_METADATA_HOST") or "metadata.google.internal" + url = ( + "http://%s/computeMetadata/v1/instance/service-accounts/default/token" + % metadata_host + ) + + headers = {"Metadata-Flavor": "Google"} + client = httpx.Client() + try: + response = client.get(url, headers=headers) + except Exception as e: + msg = "unable to retrieve GCP credentials: %s" % e + raise MongoCryptError(msg) from e + finally: + client.close() + + if response.status_code != 200: + msg = f"Unable to retrieve GCP credentials: expected StatusCode 200, got StatusCode: {response.status_code}. Response body:\n{response.content}" + raise MongoCryptError(msg) + try: + data = response.json() + except Exception as e: + raise MongoCryptError( + f"unable to retrieve GCP credentials: error reading response body\n{response.content}" + ) from e + + if not data.get("access_token"): + msg = ( + "unable to retrieve GCP credentials: got unexpected empty accessToken from GCP Metadata Server. Response body: %s" + % response.content + ) + raise MongoCryptError(msg) + + return {"accessToken": data["access_token"]} + + +def _get_azure_credentials(): + """Get on-demand Azure credentials""" + global _azure_creds_cache + # Credentials are considered expired when: Expiration - now < 1 mins. + creds = _azure_creds_cache + if creds: + if creds.expires_utc - datetime.now(tz=timezone.utc) < timedelta(seconds=60): + _azure_creds_cache = None + else: + return {"accessToken": creds.access_token} + + url = "http://169.254.169.254/metadata/identity/oauth2/token" + url += "?api-version=2018-02-01" + url += "&resource=https://vault.azure.net" + headers = {"Metadata": "true", "Accept": "application/json"} + client = httpx.Client() + try: + response = client.get(url, headers=headers) + except Exception as e: + msg = "Failed to acquire IMDS access token: %s" % e + raise MongoCryptError(msg) from e + finally: + client.close() + + if response.status_code != 200: + msg = "Failed to acquire IMDS access token." + raise MongoCryptError(msg) + try: + data = response.json() + except Exception as e: + raise MongoCryptError("Azure IMDS response must be in JSON format.") from e + + for key in ["access_token", "expires_in"]: + if not data.get(key): + msg = "Azure IMDS response must contain %s, but was %s." + msg = msg % (key, response.content) + raise MongoCryptError(msg) + + try: + expires_in = int(data["expires_in"]) + except ValueError as e: + raise MongoCryptError( + 'Azure IMDS response must contain "expires_in" integer, but was %s.' + % response.content + ) from e + + expires_utc = datetime.now(tz=timezone.utc) + timedelta(seconds=expires_in) + _azure_creds_cache = _azure_creds(data["access_token"], expires_utc) + return {"accessToken": data["access_token"]} + + +def _ask_for_kms_credentials(kms_providers): + """Get on-demand kms credentials. + + This is a separate function so it can be overridden in unit tests.""" + global _azure_creds_cache + on_demand_aws = "aws" in kms_providers and not len(kms_providers["aws"]) + on_demand_gcp = "gcp" in kms_providers and not len(kms_providers["gcp"]) + on_demand_azure = "azure" in kms_providers and not len(kms_providers["azure"]) + + if not any([on_demand_aws, on_demand_gcp, on_demand_azure]): + return {} + creds = {} + if on_demand_aws: + if not _HAVE_AUTH_AWS: + raise RuntimeError( + "On-demand AWS credentials require pymongo-auth-aws: " + "install with: python -m pip install 'pymongo[aws]'" + ) + aws_creds = aws_temp_credentials() + creds_dict = { + "accessKeyId": aws_creds.username, + "secretAccessKey": aws_creds.password, + } + if aws_creds.token: + creds_dict["sessionToken"] = aws_creds.token + creds["aws"] = creds_dict + if on_demand_gcp: + creds["gcp"] = _get_gcp_credentials() + if on_demand_azure: + try: + creds["azure"] = _get_azure_credentials() + except Exception: + _azure_creds_cache = None + raise + return creds diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/explicit_encrypter.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/explicit_encrypter.py new file mode 100644 index 0000000..f9095c5 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/explicit_encrypter.py @@ -0,0 +1,156 @@ +# Copyright 2024-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. + +from pymongocrypt.mongocrypt import MongoCrypt +from pymongocrypt.options import DataKeyOpts, ExplicitEncryptOpts +from pymongocrypt.synchronous.state_machine import run_state_machine + + +class ExplicitEncrypter: + def __init__(self, callback, mongo_crypt_opts): + """Encrypts and decrypts BSON values. + + This class is used by a driver to support explicit encryption and + decryption of individual fields in a BSON document. + + :Parameters: + - `callback`: A :class:`MongoCryptCallback`. + - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. + """ + self.callback = callback + if mongo_crypt_opts.schema_map is not None: + raise ValueError("mongo_crypt_opts.schema_map must be None") + self.mongocrypt = MongoCrypt(mongo_crypt_opts, callback) + + def create_data_key( + self, kms_provider, master_key=None, key_alt_names=None, key_material=None + ): + """Creates a data key used for explicit encryption. + + :Parameters: + - `kms_provider`: The KMS provider to use. Supported values are + "aws", "azure", "gcp", "kmip", "local", or a named provider like + "kmip:name". + - `master_key`: See class:`DataKeyOpts`. + - `key_alt_names` (optional): An optional list of string alternate + names used to reference a key. If a key is created with alternate + names, then encryption may refer to the key by the unique + alternate name instead of by ``_id``. + - `key_material`: (optional) See class:`DataKeyOpts`. + + :Returns: + The _id of the created data key document. + """ + # CDRIVER-3275 each key_alt_name needs to be wrapped in a bson + # document. + encoded_names = [] + if key_alt_names is not None: + for name in key_alt_names: + encoded_names.append(self.callback.bson_encode({"keyAltName": name})) + + if key_material is not None: + key_material = self.callback.bson_encode({"keyMaterial": key_material}) + + opts = DataKeyOpts(master_key, encoded_names, key_material) + with self.mongocrypt.data_key_context(kms_provider, opts) as ctx: + key = run_state_machine(ctx, self.callback) + return self.callback.insert_data_key(key) + + def rewrap_many_data_key(self, filter, provider=None, master_key=None): + """Decrypts and encrypts all matching data keys with a possibly new `master_key` value. + + :Parameters: + - `filter`: A document used to filter the data keys. + - `provider`: (optional) The name of a different kms provider. + - `master_key`: Optional document for the given provider. + + :Returns: + A binary document with the rewrap data. + """ + with self.mongocrypt.rewrap_many_data_key_context( + filter, provider, master_key + ) as ctx: + return run_state_machine(ctx, self.callback) + + def encrypt( + self, + value, + algorithm, + key_id=None, + key_alt_name=None, + query_type=None, + contention_factor=None, + range_opts=None, + is_expression=False, + ): + """Encrypts a BSON value. + + Note that exactly one of ``key_id`` or ``key_alt_name`` must be + provided. + + :Parameters: + - `value` (bytes): The BSON value to encrypt. + - `algorithm` (string): The encryption algorithm to use. See + :class:`Algorithm` for some valid options. + - `key_id` (bytes): The bytes of the binary subtype 4 ``_id`` data + key. For example, ``uuid.bytes`` or ``bytes(bson_binary)``. + - `key_alt_name` (string): Identifies a key vault document by + 'keyAltName'. + - `query_type` (str): The query type to execute. + - `contention_factor` (int): The contention factor to use + when the algorithm is "Indexed". + - `range_opts` (bytes): Options for explicit encryption + with the "range" algorithm encoded as a BSON document. + - `is_expression` (boolean): True if this is an encryptExpression() + context. Defaults to False. + + :Returns: + The encrypted BSON value. + + .. versionchanged:: 1.3 + Added the `query_type` and `contention_factor` parameters. + .. versionchanged:: 1.5 + Added the `range_opts` and `is_expression` parameters. + """ + # CDRIVER-3275 key_alt_name needs to be wrapped in a bson document. + if key_alt_name is not None: + key_alt_name = self.callback.bson_encode({"keyAltName": key_alt_name}) + opts = ExplicitEncryptOpts( + algorithm, + key_id, + key_alt_name, + query_type, + contention_factor, + range_opts, + is_expression, + ) + with self.mongocrypt.explicit_encryption_context(value, opts) as ctx: + return run_state_machine(ctx, self.callback) + + def decrypt(self, value): + """Decrypts a BSON value. + + :Parameters: + - `value`: The encoded document to decrypt, which must be in the + form { "v" : encrypted BSON value }}. + + :Returns: + The decrypted BSON value. + """ + with self.mongocrypt.explicit_decryption_context(value) as ctx: + return run_state_machine(ctx, self.callback) + + def close(self): + """Cleanup resources.""" + self.mongocrypt.close() diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/state_machine.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/state_machine.py new file mode 100644 index 0000000..76fb4cd --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/state_machine.py @@ -0,0 +1,149 @@ +# Copyright 2024-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. + +from abc import abstractmethod + +from pymongocrypt.binding import lib +from pymongocrypt.compat import ABC +from pymongocrypt.errors import MongoCryptError +from pymongocrypt.synchronous.credentials import _ask_for_kms_credentials + + +class MongoCryptCallback(ABC): + """Callback ABC to perform I/O on behalf of libbmongocrypt.""" + + @abstractmethod + def kms_request(self, kms_context): + """Complete a KMS request. + + :Parameters: + - `kms_context`: A :class:`MongoCryptKmsContext`. + + :Returns: + None + """ + + @abstractmethod + def collection_info(self, database, filter): + """Get the collection info for a namespace. + + The returned collection info is passed to libmongocrypt which reads + the JSON schema. + + :Parameters: + - `database`: The database on which to run listCollections. + - `filter`: The filter to pass to listCollections. + + :Returns: + The first document from the listCollections command response as BSON. + """ + + @abstractmethod + def mark_command(self, database, cmd): + """Mark a command for encryption. + + :Parameters: + - `database`: The database on which to run this command. + - `cmd`: The BSON command to run. + + :Returns: + The marked command response from mongocryptd. + """ + + @abstractmethod + def fetch_keys(self, filter): + """Yields one or more keys from the key vault. + + :Parameters: + - `filter`: The filter to pass to find. + + :Returns: + A generator which yields the requested keys from the key vault. + """ + + @abstractmethod + def insert_data_key(self, data_key): + """Insert a data key into the key vault. + + :Parameters: + - `data_key`: The data key document to insert. + + :Returns: + The _id of the inserted data key document. + """ + + @abstractmethod + def bson_encode(self, doc): + """Encode a document to BSON. + + A document can be any mapping type (like :class:`dict`). + + :Parameters: + - `doc`: mapping type representing a document + + :Returns: + The encoded BSON bytes. + """ + + @abstractmethod + def close(self): + """Release resources.""" + + +def run_state_machine(ctx, callback): + """Run the libmongocrypt state machine until completion. + + :Parameters: + - `ctx`: A :class:`MongoCryptContext`. + - `callback`: A :class:`MongoCryptCallback`. + + :Returns: + The completed libmongocrypt operation. + """ + while True: + state = ctx.state + # Check for terminal states first. + if state == lib.MONGOCRYPT_CTX_ERROR: + ctx._raise_from_status() + elif state == lib.MONGOCRYPT_CTX_READY: + return ctx.finish() + elif state == lib.MONGOCRYPT_CTX_DONE: + return None + + if state == lib.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: + list_colls_filter = ctx.mongo_operation() + coll_info = callback.collection_info(ctx.database, list_colls_filter) + if coll_info: + ctx.add_mongo_operation_result(coll_info) + ctx.complete_mongo_operation() + elif state == lib.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: + mongocryptd_cmd = ctx.mongo_operation() + result = callback.mark_command(ctx.database, mongocryptd_cmd) + ctx.add_mongo_operation_result(result) + ctx.complete_mongo_operation() + elif state == lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS: + key_filter = ctx.mongo_operation() + for key in callback.fetch_keys(key_filter): + ctx.add_mongo_operation_result(key) + ctx.complete_mongo_operation() + elif state == lib.MONGOCRYPT_CTX_NEED_KMS: + for kms_ctx in ctx.kms_contexts(): + with kms_ctx: + callback.kms_request(kms_ctx) + ctx.complete_kms() + elif state == lib.MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: + creds = _ask_for_kms_credentials(ctx.kms_providers) + ctx.provide_kms_providers(callback.bson_encode(creds)) + else: + raise MongoCryptError(f"unknown state: {state}") diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py index d41f559..133d385 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = '1.5.3.dev0' +__version__ = "1.11.0.dev0" -_MIN_LIBMONGOCRYPT_VERSION = '1.7.0' +_MIN_LIBMONGOCRYPT_VERSION = "1.8.0" diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/pyproject.toml b/ext/libmongocrypt/libmongocrypt/bindings/python/pyproject.toml new file mode 100644 index 0000000..ec0c9dc --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/pyproject.toml @@ -0,0 +1,118 @@ +[build-system] +requires = ["hatchling>1.24","hatch-requirements-txt>=0.4.1"] +build-backend = "hatchling.build" + +[project] +name = "pymongocrypt" +dynamic = ["version", "dependencies", "optional-dependencies"] +description = "Python bindings for libmongocrypt" +readme = "README.rst" +license = {file="LICENSE"} +requires-python = ">=3.8" +authors = [ + { name = "Shane Harvey", email = "mongodb-user@googlegroups.com" }, +] +keywords = [ + "bson", + "mongo", + "mongocrypt", + "mongodb", + "pymongo", + "pymongocrypt", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Database", +] + +[project.urls] +Homepage = "https://github.com/mongodb/libmongocrypt/tree/master/bindings/python" + +[tool.hatch.version] +path = "pymongocrypt/version.py" +validate-bump = false + +# Used to call hatch_build.py +[tool.hatch.build.hooks.custom] + +[tool.hatch.metadata.hooks.requirements_txt] +files = ["requirements.txt"] + +[tool.hatch.metadata.hooks.requirements_txt.optional-dependencies] +test = ["requirements-test.txt"] + +[tool.ruff.lint] +select = [ + "E", "F", "W", # flake8 + "B", # flake8-bugbear + "I", # isort + "ARG", # flake8-unused-arguments + "C4", # flake8-comprehensions + "EM", # flake8-errmsg + "ICN", # flake8-import-conventions + "G", # flake8-logging-format + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PL", # pylint + "PT", # flake8-pytest-style + "PTH", # flake8-use-pathlib + "RET", # flake8-return + "RUF", # Ruff-specific + "S", # flake8-bandit + "SIM", # flake8-simplify + "T20", # flake8-print + "UP", # pyupgrade + "YTT", # flake8-2020 + "EXE", # flake8-executable +] +ignore = [ + "PLR", # Design related pylint codes + "E501", # Line too long + "PT004", # Use underscore for non-returning fixture (use usefixture instead) + "UP007", # Use `X | Y` for type annotation + "EM101", # Exception must not use a string literal, assign to variable first + "EM102", # Exception must not use an f-string literal, assign to variable first + "G004", # Logging statement uses f-string" + "UP006", # Use `type` instead of `Type` for type annotation" + "RET505", # Unnecessary `elif` after `return` statement" + "RET506", # Unnecessary `elif` after `raise` statement + "SIM108", # Use ternary operator" + "PTH123", # `open()` should be replaced by `Path.open()`" + "SIM102", # Use a single `if` statement instead of nested `if` statements + "SIM105", # Use `contextlib.suppress(OSError)` instead of `try`-`except`-`pass` + "ARG002", # Unused method argument: + "S101", # Use of `assert` detected + "SIM114", # Combine `if` branches using logical `or` operator + "PGH003", # Use specific rule codes when ignoring type issues + "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` + "EM103", # Exception must not use a `.format()` string directly, assign to variable first + "C408", # Unnecessary `dict` call (rewrite as a literal) + "SIM117", # Use a single `with` statement with multiple contexts instead of nested `with` statements + "PLW0603", # Using the global statement to update is discouraged + "F403" # Unable to detect undefined names +] +unfixable = [ + "RUF100", # Unused noqa + "T20", # Removes print statements + "F841", # Removes unused variables +] + +[tool.ruff.lint.per-file-ignores] +"test/*.py" = ["PT", "E402", "PLW", "SIM", "E741", "PTH", "S", "B904", "E722", "T201", + "RET", "ARG", "F405", "B028", "PGH001", "B018", "F403", "RUF015", "E731", "B007", + "UP031", "F401", "B023", "F811"] +"pymongocrypt/crypto.py" = ["ARG001"] diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/release.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/release.sh index d8932f4..2b67658 100755 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/release.sh +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/release.sh @@ -1,92 +1,128 @@ #!/bin/bash -ex # This script should be run on macOS and Cygwin on Windows. -# On macOS it will create the following distributions: +# On macOS it will create the following distributions # pymongocrypt-.tar.gz -# pymongocrypt--py2.py3-none-manylinux2010_x86_64.whl -# pymongocrypt--py2.py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl -# pymongocrypt--py2.py3-none-macosx_10_9_x86_64.whl +# pymongocrypt--py3-none-macosx_11_0_universal2.whl +# pymongocrypt--py3-none-macosx_10_14_intel.whl # # On Windows it will create the following distribution: -# pymongocrypt--py2.py3-none-win_amd64.whl +# pymongocrypt--py3-none-win_amd64.whl +# +# If docker is available on Linux or MacOS, it will also produce the following: +# pymongocrypt--py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl set -o xtrace # Write all commands first to stderr set -o errexit # Exit the script with error if any of the commands fail # The libmongocrypt git revision release to embed in our wheels. -REVISION=$(git rev-list -n 1 1.7.3) +LIBMONGOCRYPT_VERSION=$(cat ./libmongocrypt-version.txt) +REVISION=$(git rev-list -n 1 $LIBMONGOCRYPT_VERSION) # The libmongocrypt release branch. -BRANCH="r1.7" -MACOS_TARGET=${MACOS_TARGET:="macos"} +BRANCH="r1.10" +# The python executable to use. +PYTHON=${PYTHON:-python} -if [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin - rm -rf venv37 - virtualenv -p C:\\python\\Python37\\python.exe venv37 && . ./venv37/Scripts/activate +# Clean slate. +rm -rf dist .venv build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib - # Build the Windows wheel. +function get_libmongocrypt() { + TARGET=$1 + MONGOCRYPT_SO=$2 rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib - curl -O https://s3.amazonaws.com/mciuploads/libmongocrypt-release/windows-test/${BRANCH}/${REVISION}/libmongocrypt.tar.gz + curl -O https://s3.amazonaws.com/mciuploads/libmongocrypt-release/$TARGET/${BRANCH}/${REVISION}/libmongocrypt.tar.gz mkdir libmongocrypt tar xzf libmongocrypt.tar.gz -C ./libmongocrypt - NOCRYPTO_SO=libmongocrypt/nocrypto/bin/mongocrypt.dll - chmod +x ${NOCRYPTO_SO} - cp ${NOCRYPTO_SO} pymongocrypt/ + chmod +x ${MONGOCRYPT_SO} + cp ${MONGOCRYPT_SO} pymongocrypt/ rm -rf ./libmongocrypt libmongocrypt.tar.gz +} - # Ensure updated deps. - python -m pip install --upgrade pip setuptools wheel - - python setup.py bdist_wheel +function build_wheel() { + python -m pip install unasync + python -m pip install --upgrade pip build + python -m build --wheel rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib - ls dist -elif [ "Darwin" = "$(uname -s)" ]; then - # Build the mac wheel. - PYTHON=${PYTHON:="/Library/Frameworks/Python.framework/Versions/3.10/bin/python3"} +} - # Ensure updated deps. - $PYTHON -m pip install --upgrade pip setuptools wheel +function build_manylinux_wheel() { + python -m pip install unasync + docker pull $1 + docker run --rm -v `pwd`:/python $1 /python/build-manylinux-wheel.sh + # Sudo is needed to remove the files created by docker. + sudo rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib +} - rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib +function test_dist() { + python -m pip uninstall -y pymongocrypt + python -m pip install $1 + pushd .. + python -c "from pymongocrypt.binding import libmongocrypt_version, lib" + popd +} - # Install the sdist. - $PYTHON setup.py sdist +# Handle Windows dist. +if [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin + $PYTHON -m venv .venv + # Workaround https://bugs.python.org/issue32451: + # .venv/Scripts/activate: line 3: $'\r': command not found + dos2unix .venv/Scripts/activate || true + . ./.venv/Scripts/activate - curl -O https://s3.amazonaws.com/mciuploads/libmongocrypt-release/${MACOS_TARGET}/${BRANCH}/${REVISION}/libmongocrypt.tar.gz - mkdir libmongocrypt - tar xzf libmongocrypt.tar.gz -C ./libmongocrypt - NOCRYPTO_SO=libmongocrypt/nocrypto/lib/libmongocrypt.dylib - chmod +x ${NOCRYPTO_SO} - cp ${NOCRYPTO_SO} pymongocrypt/ - rm -rf ./libmongocrypt libmongocrypt.tar.gz + # Use crypto-enabled libmongocrypt. + get_libmongocrypt windows-test libmongocrypt/bin/mongocrypt.dll + build_wheel + test_dist dist/*.whl +fi - $PYTHON setup.py bdist_wheel - rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib - ls dist +# Handle MacOS dists. +if [ "Darwin" = "$(uname -s)" ]; then + $PYTHON -m venv .venv + . .venv/bin/activate + + # Build universal2 wheel. + get_libmongocrypt macos libmongocrypt/lib/libmongocrypt.dylib + export MACOSX_DEPLOYMENT_TARGET=11.0 + export _PYTHON_HOST_PLATFORM=macosx-11.0-universal2 + build_wheel + if [ "$(uname -m)" == "arm64" ]; then + test_dist dist/*universal2.whl + fi + + # Build and test sdist. + python -m build --sdist + test_dist dist/*.tar.gz fi +# Handle manylinux dists. if [ $(command -v docker) ]; then - # Build the manylinux2010 wheels. - rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib - curl -O https://s3.amazonaws.com/mciuploads/libmongocrypt-release/rhel-62-64-bit/${BRANCH}/${REVISION}/libmongocrypt.tar.gz - mkdir libmongocrypt - tar xzf libmongocrypt.tar.gz -C ./libmongocrypt - NOCRYPTO_SO=libmongocrypt/nocrypto/lib64/libmongocrypt.so - chmod +x ${NOCRYPTO_SO} - cp ${NOCRYPTO_SO} pymongocrypt/ - rm -rf ./libmongocrypt libmongocrypt.tar.gz + if [ "Windows_NT" = "$OS" ]; then + # docker: Error response from daemon: Windows does not support privileged mode + # would be raised by the qemu command below. + echo "Not supported on Windows" + exit 0 + fi - # 2021-05-05-1ac6ef3 was the last release to generate pip < 20.3 compatible - # wheels. After that auditwheel was upgraded to v4 which produces PEP 600 - # manylinux_x_y wheels which requires pip >= 20.3. We use the older docker - # image to support older pip versions. - images=(quay.io/pypa/manylinux2010_x86_64:2021-05-05-1ac6ef3 \ - quay.io/pypa/manylinux2010_x86_64) - for image in "${images[@]}"; do - docker pull $image - docker run --rm -v `pwd`:/python $image /python/build-manylinux-wheel.sh - done + # Set up qemu support using the method used in docker/setup-qemu-action + # https://github.com/docker/setup-qemu-action/blob/2b82ce82d56a2a04d2637cd93a637ae1b359c0a7/README.md?plain=1#L46 + docker run --rm --privileged tonistiigi/binfmt:latest --install all - # Sudo is needed to remove the files created by docker. - sudo rm -rf build libmongocrypt pymongocrypt/*.so pymongocrypt/*.dll pymongocrypt/*.dylib - ls dist + # Build the manylinux2014 x86_64 wheel. + # https://github.com/pypa/manylinux + # Supports CentOS 7 rh-python38, CentOS 8 python38, Fedora 32+, Ubuntu 20.04+. + # When the rhel7 images go EOL we'll have to switch to the manylinux_x_y variants + # and use rhel8. + get_libmongocrypt rhel-70-64-bit libmongocrypt/nocrypto/lib64/libmongocrypt.so + build_manylinux_wheel quay.io/pypa/manylinux2014_x86_64:2023-12-05-e9f0345 + if [ "Linux" = "$(uname -s)" ]; then + $PYTHON -m venv .venv + . .venv/bin/activate + test_dist dist/*linux*.whl + fi + + # Build the manylinux_2_28 aarch64 wheel. + get_libmongocrypt rhel-82-arm64 libmongocrypt/nocrypto/lib64/libmongocrypt.so + build_manylinux_wheel quay.io/pypa/manylinux_2_28_aarch64:2024-01-01-0e91b08 fi + +ls -ltr dist diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test-requirements.txt b/ext/libmongocrypt/libmongocrypt/bindings/python/requirements-test.txt similarity index 56% rename from ext/libmongocrypt/libmongocrypt/bindings/python/test-requirements.txt rename to ext/libmongocrypt/libmongocrypt/bindings/python/requirements-test.txt index 06e5a08..710c0be 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test-requirements.txt +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/requirements-test.txt @@ -1,4 +1,7 @@ pymongo[aws]>=4 cffi>=1.12.0,<2 cryptography>=2 -requests_mock>=1.10 +pytest>=7.0 +unasync +respx +setuptools diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/requirements.txt b/ext/libmongocrypt/libmongocrypt/bindings/python/requirements.txt new file mode 100644 index 0000000..f95140d --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/requirements.txt @@ -0,0 +1,4 @@ +cffi>=1.12.0,<2 +cryptography>=40 +packaging>=21.0 +httpx>=0.25.0 diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/sbom.json b/ext/libmongocrypt/libmongocrypt/bindings/python/sbom.json new file mode 100644 index 0000000..605d4ff --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/sbom.json @@ -0,0 +1,76 @@ +{ + "components": [ + { + "bom-ref": "pkg:github/mongodb/libmongocrypt@1.10.1", + "externalReferences": [ + { + "type": "distribution", + "url": "https://github.com/mongodb/libmongocrypt/archive/refs/tags/1.10.1.tar.gz" + }, + { + "type": "website", + "url": "https://github.com/mongodb/libmongocrypt/tree/1.10.1" + } + ], + "group": "mongodb", + "name": "libmongocrypt", + "purl": "pkg:github/mongodb/libmongocrypt@1.10.1", + "type": "library", + "version": "1.10.1" + } + ], + "dependencies": [ + { + "ref": "pkg:github/mongodb/libmongocrypt@1.10.1" + } + ], + "metadata": { + "timestamp": "2024-06-28T19:11:17.100829+00:00", + "tools": [ + { + "externalReferences": [ + { + "type": "build-system", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/actions" + }, + { + "type": "distribution", + "url": "https://pypi.org/project/cyclonedx-python-lib/" + }, + { + "type": "documentation", + "url": "https://cyclonedx-python-library.readthedocs.io/" + }, + { + "type": "issue-tracker", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/issues" + }, + { + "type": "license", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE" + }, + { + "type": "release-notes", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md" + }, + { + "type": "vcs", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib" + }, + { + "type": "website", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" + } + ], + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "6.4.4" + } + ] + }, + "serialNumber": "urn:uuid:b09e93cf-eb1b-4d38-add5-86b01139769f", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.5" +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/setup.py b/ext/libmongocrypt/libmongocrypt/bindings/python/setup.py deleted file mode 100644 index 2a1b304..0000000 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/setup.py +++ /dev/null @@ -1,89 +0,0 @@ -import os -import sys - -from setuptools import setup, find_packages - -if sys.version_info[:3] < (3, 7): - raise RuntimeError("pymongocrypt requires Python version >= 3.7") - -# Make our Windows and macOS wheels platform specific because we embed -# libmongocrypt. On Linux we ship manylinux2010 wheels which cannot do this or -# else auditwheel raises the following error: -# RuntimeError: Invalid binary wheel, found the following shared -# library/libraries in purelib folder: -# libmongocrypt.so -# The wheel has to be platlib compliant in order to be repaired by auditwheel. -cmdclass = {} -if sys.platform in ('win32', 'darwin'): - try: - from wheel.bdist_wheel import bdist_wheel as _bdist_wheel - class bdist_wheel(_bdist_wheel): - - def finalize_options(self): - _bdist_wheel.finalize_options(self) - self.root_is_pure = False - - def get_tag(self): - python, abi, plat = _bdist_wheel.get_tag(self) - # Our python source is py3 compatible. - python, abi = 'py3', 'none' - return python, abi, plat - - cmdclass['bdist_wheel'] = bdist_wheel - except ImportError: - # Version of wheel is too old, use None to fail a bdist_wheel attempt. - cmdclass['bdist_wheel'] = None - -with open('README.rst', 'rb') as f: - LONG_DESCRIPTION = f.read().decode('utf8') - -# Single source the version. -version_file = os.path.realpath(os.path.join( - os.path.dirname(__file__), 'pymongocrypt', 'version.py')) -version = {} -with open(version_file) as fp: - exec(fp.read(), version) - -setup( - name="pymongocrypt", - version=version['__version__'], - description="Python bindings for libmongocrypt", - long_description=LONG_DESCRIPTION, - packages=find_packages(exclude=['test']), - package_data={'pymongocrypt': ['*.dll', '*.so', '*.dylib']}, - zip_safe=False, - # Note cryptography is uncapped because it does not follow semver. - install_requires=[ - "cffi>=1.12.0,<2", - "cryptography>=2.0", - # cryptography 40 dropped support for PyPy <7.3.10. - "cryptography<40;platform_python_implementation=='PyPy' and implementation_version<'7.3.10'", - "requests<3.0.0" - ], - author="Shane Harvey", - author_email="mongodb-user@googlegroups.com", - url="https://github.com/mongodb/libmongocrypt/tree/master/bindings/python", - keywords=["mongo", "mongodb", "pymongocrypt", "pymongo", "mongocrypt", - "bson"], - test_suite="test", - license="Apache License, Version 2.0", - python_requires=">=3.7", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Topic :: Database"], - cmdclass=cmdclass, -) diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/strip_header.py b/ext/libmongocrypt/libmongocrypt/bindings/python/strip_header.py index 52cfdf0..fcc5426 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/strip_header.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/strip_header.py @@ -21,16 +21,16 @@ import re import sys -DROP_RE = re.compile(r'^\s*(#|MONGOCRYPT_EXPORT)') +DROP_RE = re.compile(r"^\s*(#|MONGOCRYPT_EXPORT)") def strip_file(content): - fold = content.replace('\\\n', ' ') - all_lines = fold.split('\n') + [''] + fold = content.replace("\\\n", " ") + all_lines = [*fold.split("\n"), ""] keep_lines = (line for line in all_lines if not DROP_RE.match(line)) - fin = '' + fin = "" for line, peek in itertools.pairwise(keep_lines): - if peek == '' and line == '': + if peek == "" and line == "": # Drop adjacent empty lines continue yield line @@ -38,11 +38,10 @@ def strip_file(content): yield fin - def strip(hdr): with open(hdr) as fp: out = strip_file(fp.read()) - print('\n'.join(out)) + print("\n".join(out)) # noqa: T201 if __name__ == "__main__": diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/synchro.py b/ext/libmongocrypt/libmongocrypt/bindings/python/synchro.py new file mode 100644 index 0000000..a9a6ba6 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/synchro.py @@ -0,0 +1,64 @@ +# Copyright 2024-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. + +from os import listdir +from pathlib import Path + +from unasync import Rule, unasync_files + +replacements = { + "asynchronous": "synchronous", + "AsyncMongoCryptCallback": "MongoCryptCallback", + "AsyncExplicitEncrypter": "ExplicitEncrypter", + "AsyncAutoEncrypter": "AutoEncrypter", + "AsyncClient": "Client", + "AsyncMongoCrypt": "MongoCrypt", + "aclose": "close", +} + +_base = "pymongocrypt" + +async_files = [ + f"./{_base}/asynchronous/{f}" + for f in listdir("pymongocrypt/asynchronous") + if (Path(_base) / "asynchronous" / f).is_file() +] + + +unasync_files( + async_files, + [ + Rule( + fromdir="/pymongocrypt/asynchronous/", + todir="/pymongocrypt/synchronous/", + additional_replacements=replacements, + ) + ], +) + +sync_files = [ + f"./{_base}/synchronous/{f}" + for f in listdir("pymongocrypt/synchronous") + if (Path(_base) / "synchronous" / f).is_file() +] + +for file in sync_files: + with open(file, "r+") as f: + lines = f.readlines() + for i in range(len(lines)): + for s in replacements: + lines[i] = lines[i].replace(s, replacements[s]) + f.seek(0) + f.truncate() + f.writelines(lines) diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/__init__.py b/ext/libmongocrypt/libmongocrypt/bindings/python/test/__init__.py index e00db3e..4274c1d 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/__init__.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/__init__.py @@ -21,6 +21,7 @@ # Enable the fault handler to dump the traceback of each running thread # after a segfault. import faulthandler + faulthandler.enable() except ImportError: pass diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/collection-info.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/collection-info.json index 3d1993d..a2a6204 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/collection-info.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/collection-info.json @@ -36,4 +36,4 @@ } } } -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/command.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/command.json index d04bf77..0fa3fee 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/command.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/command.json @@ -3,4 +3,4 @@ "filter": { "ssn": "457-55-5462" } -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/compact/success/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/compact/success/encrypted-payload.json index c6dc271..7eb7ea7 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/compact/success/encrypted-payload.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/compact/success/encrypted-payload.json @@ -1,23 +1,23 @@ { - "compactStructuredEncryptionData": "test", - "compactionTokens": { - "nested.notindexed": { - "$binary": { - "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", - "subType": "00" - } - }, - "nested.encrypted": { - "$binary": { - "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", - "subType": "00" - } - }, - "encrypted": { - "$binary": { - "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", - "subType": "00" - } + "compactStructuredEncryptionData": "test", + "compactionTokens": { + "nested.notindexed": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" } - } -} \ No newline at end of file + }, + "nested.encrypted": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "encrypted": { + "$binary": { + "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", + "subType": "00" + } + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/encrypted-command-reply.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/encrypted-command-reply.json index 73d4d34..0548cb5 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/encrypted-command-reply.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/encrypted-command-reply.json @@ -13,4 +13,4 @@ "ns" : "test.test" }, "ok" : 1 -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/encrypted-field-config-map.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/encrypted-field-config-map.json index e0dc506..043ecec 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/encrypted-field-config-map.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/encrypted-field-config-map.json @@ -45,4 +45,4 @@ } ] } -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit-v2/int32/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit-v2/int32/encrypted-payload.json index 796f336..3c8ab7b 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit-v2/int32/encrypted-payload.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit-v2/int32/encrypted-payload.json @@ -5,7 +5,7 @@ "age": { "$gte": { "$binary": { - "base64": "Dd0BAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAAA==", + "base64": "DQECAAADcGF5bG9hZACZAQAABGcAhQEAAAMwAH0AAAAFZAAgAAAAAInd0noBhIiJMv8QTjcfgRqnnVhxRJRRACLfvgT+CTR/BXMAIAAAAADm0EjqF/T4EmR6Dw6NaPLrL0OuzS4AFvm90czFluAAygVsACAAAAAA5MXcYWjYlzhPFUDebBEa17B5z2bupmaW9uCdtLjc7RkAAzEAfQAAAAVkACAAAAAA7lkNtT6RLw91aJ07K/blwlFs5wi9pQjqUXDcaCTxe98FcwAgAAAAAPwySffuLQihmF70Ot93KtaUMNU8KpmA+niyPRcvarNMBWwAIAAAAACDv6fJXXwRqwZH3O2kO+hdeLZ36U6bMZSui8kv0PsPtAADMgB9AAAABWQAIAAAAACcMWVTbZC4ox5VdjWeYKLgf4oBjpPlbTTAkucm9JPK0wVzACAAAAAA3tIww4ZTytkxFsUKyJbc3zwQ2w7DhkOqaNvX9g8pi3gFbAAgAAAAAGs9XR3Q1JpxV+HPW8P2GvCuCBF5bGZ8Kl1zHqzZcd5/AAASY20ABAAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAEnNwAAEAAAAAAAAAEHRmAAAAAAAQbW4AAAAAABBteADIAAAAAA==", "subType": "06" } } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit-v2/int32/rangeopts.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit-v2/int32/rangeopts.json index 5ef3da4..8a769fb 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit-v2/int32/rangeopts.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit-v2/int32/rangeopts.json @@ -7,5 +7,8 @@ }, "sparsity": { "$numberLong": "1" + }, + "trimFactor": { + "$numberInt": "0" } } diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-rangePreview-explicit/int32/rangeopts.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-rangePreview-explicit/int32/rangeopts.json new file mode 100644 index 0000000..5ef3da4 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-rangePreview-explicit/int32/rangeopts.json @@ -0,0 +1,11 @@ +{ + "min": { + "$numberInt": "0" + }, + "max": { + "$numberInt": "200" + }, + "sparsity": { + "$numberLong": "1" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-rangePreview-explicit/int32/value-to-encrypt.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-rangePreview-explicit/int32/value-to-encrypt.json new file mode 100644 index 0000000..4c294e8 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-rangePreview-explicit/int32/value-to-encrypt.json @@ -0,0 +1,20 @@ +{ + "v": { + "$and": [ + { + "age": { + "$gte": { + "$numberInt": "23" + } + } + }, + { + "age": { + "$lte": { + "$numberInt": "35" + } + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document-azure.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document-azure.json index fd36548..0885d1d 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document-azure.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document-azure.json @@ -30,4 +30,4 @@ } }, "keyAltNames": ["name1", "name2"] -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document-gcp.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document-gcp.json index 11d6d9d..79978c4 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document-gcp.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document-gcp.json @@ -32,4 +32,4 @@ } }, "keyAltNames": ["name1", "name2"] -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document.json index e28e2b2..6ad6a32 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-document.json @@ -30,4 +30,4 @@ } }, "keyAltNames": ["name1", "name2"] -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-filter.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-filter.json index 9ad7c70..4b4bf73 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-filter.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/key-filter.json @@ -16,4 +16,4 @@ } } ] -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/list-collections-filter.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/list-collections-filter.json index 2f37dc5..600e5f1 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/list-collections-filter.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/list-collections-filter.json @@ -1,3 +1,3 @@ { "name": "test" -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/mongocryptd-command.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/mongocryptd-command.json index 234a82e..8e9a269 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/mongocryptd-command.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/mongocryptd-command.json @@ -23,4 +23,4 @@ "bsonType": "object" }, "isRemoteSchema": true -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/mongocryptd-reply.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/mongocryptd-reply.json index 15feb77..481daca 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/mongocryptd-reply.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/mongocryptd-reply.json @@ -17,4 +17,4 @@ } }, "hasEncryptedPlaceholders": true -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/schema-map.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/schema-map.json index b5be71a..2bd4f0b 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/schema-map.json +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/schema-map.json @@ -37,4 +37,4 @@ }, "bsonType": "object" } -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/performance/keyDocument.json b/ext/libmongocrypt/libmongocrypt/bindings/python/test/performance/keyDocument.json new file mode 100644 index 0000000..b84b05c --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/performance/keyDocument.json @@ -0,0 +1,24 @@ +{ + "_id": { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "ACR7Hm33dDOAAD7l2ubZhSpSUWK8BkALUY+qW3UgBAEcTV8sBwZnaAWnzDsmrX55dgmYHWfynDlJogC/e33u6pbhyXvFTs5ow9OLCuCWBJ39T/Ivm3kMaZJybkejY0V+uc4UEdHvVVz/SbitVnzs2WXdMGmo1/HmDRrxGYZjewFslquv8wtUHF5pyB+QDlQBd/al9M444/8bJZFbMSmtIg==", + "subType": "00" + } + }, + "creationDate": { + "$date": "2023-08-21T14:28:20.875Z" + }, + "updateDate": { + "$date": "2023-08-21T14:28:20.875Z" + }, + "status": 0, + "masterKey": { + "provider": "local" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/performance/perf_test.py b/ext/libmongocrypt/libmongocrypt/bindings/python/test/performance/perf_test.py new file mode 100644 index 0000000..2d66063 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/performance/perf_test.py @@ -0,0 +1,165 @@ +# Copyright 2023-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. + +"""Benchmark pymongocrypt performance.""" +from __future__ import annotations + +import os +import sys +import time +import unittest +from concurrent.futures import ThreadPoolExecutor +from typing import List + +try: + import simplejson as json +except ImportError: + import json # type: ignore[no-redef] + +import bson +from bson import json_util + +sys.path[0:0] = [""] + + +from test.test_mongocrypt import MockCallback + +from pymongocrypt.binding import lib, libmongocrypt_version +from pymongocrypt.mongocrypt import MongoCrypt, MongoCryptOptions +from pymongocrypt.synchronous.explicit_encrypter import ExplicitEncrypter +from pymongocrypt.version import __version__ + +NUM_ITERATIONS = 10 +MAX_TIME = 1 +NUM_FIELDS = 1500 +LOCAL_MASTER_KEY = ( + b"\x9d\x94K\r\x93\xd0\xc5D\xa5r\xfd2\x1b\x940\x90#5s|\xf0\xf6\xc2\xf4\xda#V\xe7\x8f\x04" + b"\xcc\xfa\xdeu\xb4Q\x87\xf3\x8b\x97\xd7KD;\xac9\xa2\xc6M\x91\x00>\xd1\xfaJ0\xc1\xd2" + b"\xc6^\xfb\xacA\xf2H\x13<\x9bP\xfc\xa7$z.\x02c\xa3\xc6\x16%QPx>\x0f\xd8n\x84\xa6\xec" + b"\x8d-$G\xe5\xaf" +) + +OUTPUT_FILE = os.environ.get("OUTPUT_FILE") + +result_data: List = [] + + +def read(filename, **kwargs): + with open(os.path.join(os.path.dirname(__file__), filename), **kwargs) as fp: + return fp.read() + + +def json_data(filename): + return json_util.loads(read(filename)) + + +def bson_data(filename): + return bson.encode(json_data(filename)) + + +def tearDownModule(): + output = json.dumps(result_data, indent=4) + if OUTPUT_FILE: + with open(OUTPUT_FILE, "w") as opf: + opf.write(output) + else: + print(output) + + +class TestBulkDecryption(unittest.TestCase): + def setUp(self): + opts = MongoCryptOptions({"local": {"key": LOCAL_MASTER_KEY}}) + callback = MockCallback(key_docs=[bson_data("keyDocument.json")]) + self.mongocrypt = MongoCrypt(opts, callback) + self.encrypter = ExplicitEncrypter(callback, opts) + self.addCleanup(self.mongocrypt.close) + self.addCleanup(self.encrypter.close) + + def do_task(self, encrypted, duration=MAX_TIME): + start = time.monotonic() + ops = 0 + while time.monotonic() - start < duration: + with self.mongocrypt.decryption_context(encrypted) as ctx: + if ctx.state == lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS: + # Key is requested on the first operation, then expected to be cached for one minute. + ctx.add_mongo_operation_result(bson_data("keyDocument.json")) + ctx.complete_mongo_operation() + self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_READY) + decrypted = ctx.finish() + ops += 1 + # Assert that decryption actually occurred. + self.assertGreater(ops, 0) + doc = bson.decode(decrypted) + for val in doc.values(): + self.assertIsInstance(val, str) + return ops + + def percentile(self, percentile): + sorted_results = sorted(self.results) + percentile_index = int(len(sorted_results) * percentile / 100) - 1 + return sorted_results[percentile_index] + + def runTest(self): + doc = {} + key_id = json_data("keyDocument.json")["_id"] + for i in range(NUM_FIELDS): + val = f"value {i:04}" + val_encrypted = bson.decode( + self.encrypter.encrypt( + bson.encode({"v": val}), + "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", + key_id=key_id, + ) + )["v"] + doc[f"key{i:04}"] = val_encrypted + encrypted = bson.encode(doc) + # Warm up benchmark and discard the result. + self.do_task(encrypted, duration=2) + + for n_threads in [1, 2, 8, 64]: + with ThreadPoolExecutor(max_workers=n_threads) as executor: + self.results = [] + for _ in range(NUM_ITERATIONS): + start = time.monotonic() + thread_results = list( + executor.map(self.do_task, [encrypted] * n_threads) + ) + interval = time.monotonic() - start + self.results.append(sum(thread_results) / interval) + median = self.percentile(50) + print( + f"Finished {self.__class__.__name__}, threads={n_threads}, median ops_per_second={median:.2f}" + ) + # Remove "Test" so that TestBulkDecryption is reported as "BulkDecryption". + name = self.__class__.__name__[4:] + result_data.append( + { + "info": { + "test_name": name, + "args": { + "threads": n_threads, + }, + }, + "metrics": [ + {"name": "ops_per_second", "type": "MEDIAN", "value": median}, + ], + } + ) + + +if __name__ == "__main__": + print( + f"Running benchmark with pymongocrypt: {__version__} libmongocrypt: {libmongocrypt_version()}" + ) + unittest.main() diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_binding.py b/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_binding.py index eec4460..9462ba2 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_binding.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_binding.py @@ -18,18 +18,17 @@ sys.path[0:0] = [""] -import pymongocrypt -from pymongocrypt.binding import ffi, lib, _parse_version - from test import unittest +import pymongocrypt +from pymongocrypt.binding import _parse_version, ffi, lib -class TestBinding(unittest.TestCase): +class TestBinding(unittest.TestCase): def assertVersionLike(self, version): self.assertTrue(isinstance(version, str), msg=version) # There should be at least one dot: "1.0" or "1.0.0" not "1". - self.assertGreaterEqual(len(version.split('.')), 2, msg=version) + self.assertGreaterEqual(len(version.split(".")), 2, msg=version) def test_pymongocrypt_version(self): self.assertVersionLike(pymongocrypt.__version__) @@ -54,17 +53,14 @@ def test_mongocrypt_status_new(self): def test_parse_version(self): # Dev versions, betas, RCs should be less than stable releases. - for v in ('1.1.0-beta1', '1.1.0-b2', '1.1.0-rc1', - '1.1.0-beta1', '1.1.0-pre1'): - self.assertLess(_parse_version(v), - _parse_version('1.1.0')) + for v in ("1.1.0-beta1", "1.1.0-b2", "1.1.0-rc1", "1.1.0-beta1", "1.1.0-pre1"): + self.assertLess(_parse_version(v), _parse_version("1.1.0")) # Dev versions should parse correctly. - _parse_version('1.1.0-beta1+20201102git80202647fc') + _parse_version("1.1.0-beta1+20201102git80202647fc") # Hyphenation in patch version should be disregarded. - self.assertEqual(_parse_version('1.1.0-beta1'), - _parse_version('1.1.0beta1')) + self.assertEqual(_parse_version("1.1.0-beta1"), _parse_version("1.1.0beta1")) if __name__ == "__main__": diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_crypto.py b/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_crypto.py index 111e519..f52d425 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_crypto.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_crypto.py @@ -19,30 +19,28 @@ sys.path[0:0] = [""] import base64 +from test import unittest from pymongocrypt.binary import MongoCryptBinaryIn from pymongocrypt.binding import ffi, lib from pymongocrypt.crypto import sign_rsaes_pkcs1_v1_5 -from test import unittest - class TestCrypto(unittest.TestCase): def test_sign_rsaes_pkcs1_v1_5(self): - key_b64 = 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4JOyv5z05cL18ztpknRC7CFY2gYol4DAKerdVUoDJxCTmFMf39dVUEqD0WDiw/qcRtSO1/FRut08PlSPmvbyKetsLoxlpS8lukSzEFpFK7+L+R4miFOl6HvECyg7lbC1H/WGAhIz9yZRlXhRo9qmO/fB6PV9IeYtU+1xYuXicjCDPp36uuxBAnCz7JfvxJ3mdVc0vpSkbSb141nWuKNYR1mgyvvL6KzxO6mYsCo4hRAdhuizD9C4jDHk0V2gDCFBk0h8SLEdzStX8L0jG90/Og4y7J1b/cPo/kbYokkYisxe8cPlsvGBf+rZex7XPxc1yWaP080qeABJb+S88O//LAgMBAAECggEBAKVxP1m3FzHBUe2NZ3fYCc0Qa2zjK7xl1KPFp2u4CU+9sy0oZJUqQHUdm5CMprqWwIHPTftWboFenmCwrSXFOFzujljBO7Z3yc1WD3NJl1ZNepLcsRJ3WWFH5V+NLJ8Bdxlj1DMEZCwr7PC5+vpnCuYWzvT0qOPTl9RNVaW9VVjHouJ9Fg+s2DrShXDegFabl1iZEDdI4xScHoYBob06A5lw0WOCTayzw0Naf37lM8Y4psRAmI46XLiF/Vbuorna4hcChxDePlNLEfMipICcuxTcei1RBSlBa2t1tcnvoTy6cuYDqqImRYjp1KnMKlKQBnQ1NjS2TsRGm+F0FbreVCECgYEA4IDJlm8q/hVyNcPe4OzIcL1rsdYN3bNm2Y2O/YtRPIkQ446ItyxD06d9VuXsQpFp9jNACAPfCMSyHpPApqlxdc8z/xATlgHkcGezEOd1r4E7NdTpGg8y6Rj9b8kVlED6v4grbRhKcU6moyKUQT3+1B6ENZTOKyxuyDEgTwZHtFECgYEA0fqdv9h9s77d6eWmIioP7FSymq93pC4umxf6TVicpjpMErdD2ZfJGulN37dq8FOsOFnSmFYJdICj/PbJm6p1i8O21lsFCltEqVoVabJ7/0alPfdG2U76OeBqI8ZubL4BMnWXAB/VVEYbyWCNpQSDTjHQYs54qa2I0dJB7OgJt1sCgYEArctFQ02/7H5Rscl1yo3DBXO94SeiCFSPdC8f2Kt3MfOxvVdkAtkjkMACSbkoUsgbTVqTYSEOEc2jTgR3iQ13JgpHaFbbsq64V0QP3TAxbLIQUjYGVgQaF1UfLOBv8hrzgj45z/ST/G80lOl595+0nCUbmBcgG1AEWrmdF0/3RmECgYAKvIzKXXB3+19vcT2ga5Qq2l3TiPtOGsppRb2XrNs9qKdxIYvHmXo/9QP1V3SRW0XoD7ez8FpFabp42cmPOxUNk3FK3paQZABLxH5pzCWI9PzIAVfPDrm+sdnbgG7vAnwfL2IMMJSA3aDYGCbF9EgefG+STcpfqq7fQ6f5TBgLFwKBgCd7gn1xYL696SaKVSm7VngpXlczHVEpz3kStWR5gfzriPBxXgMVcWmcbajRser7ARpCEfbxM1UJyv6oAYZWVSNErNzNVb4POqLYcCNySuC6xKhs9FrEQnyKjyk8wI4VnrEMGrQ8e+qYSwYk9Gh6dKGoRMAPYVXQAO0fIsHF/T0a' + key_b64 = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4JOyv5z05cL18ztpknRC7CFY2gYol4DAKerdVUoDJxCTmFMf39dVUEqD0WDiw/qcRtSO1/FRut08PlSPmvbyKetsLoxlpS8lukSzEFpFK7+L+R4miFOl6HvECyg7lbC1H/WGAhIz9yZRlXhRo9qmO/fB6PV9IeYtU+1xYuXicjCDPp36uuxBAnCz7JfvxJ3mdVc0vpSkbSb141nWuKNYR1mgyvvL6KzxO6mYsCo4hRAdhuizD9C4jDHk0V2gDCFBk0h8SLEdzStX8L0jG90/Og4y7J1b/cPo/kbYokkYisxe8cPlsvGBf+rZex7XPxc1yWaP080qeABJb+S88O//LAgMBAAECggEBAKVxP1m3FzHBUe2NZ3fYCc0Qa2zjK7xl1KPFp2u4CU+9sy0oZJUqQHUdm5CMprqWwIHPTftWboFenmCwrSXFOFzujljBO7Z3yc1WD3NJl1ZNepLcsRJ3WWFH5V+NLJ8Bdxlj1DMEZCwr7PC5+vpnCuYWzvT0qOPTl9RNVaW9VVjHouJ9Fg+s2DrShXDegFabl1iZEDdI4xScHoYBob06A5lw0WOCTayzw0Naf37lM8Y4psRAmI46XLiF/Vbuorna4hcChxDePlNLEfMipICcuxTcei1RBSlBa2t1tcnvoTy6cuYDqqImRYjp1KnMKlKQBnQ1NjS2TsRGm+F0FbreVCECgYEA4IDJlm8q/hVyNcPe4OzIcL1rsdYN3bNm2Y2O/YtRPIkQ446ItyxD06d9VuXsQpFp9jNACAPfCMSyHpPApqlxdc8z/xATlgHkcGezEOd1r4E7NdTpGg8y6Rj9b8kVlED6v4grbRhKcU6moyKUQT3+1B6ENZTOKyxuyDEgTwZHtFECgYEA0fqdv9h9s77d6eWmIioP7FSymq93pC4umxf6TVicpjpMErdD2ZfJGulN37dq8FOsOFnSmFYJdICj/PbJm6p1i8O21lsFCltEqVoVabJ7/0alPfdG2U76OeBqI8ZubL4BMnWXAB/VVEYbyWCNpQSDTjHQYs54qa2I0dJB7OgJt1sCgYEArctFQ02/7H5Rscl1yo3DBXO94SeiCFSPdC8f2Kt3MfOxvVdkAtkjkMACSbkoUsgbTVqTYSEOEc2jTgR3iQ13JgpHaFbbsq64V0QP3TAxbLIQUjYGVgQaF1UfLOBv8hrzgj45z/ST/G80lOl595+0nCUbmBcgG1AEWrmdF0/3RmECgYAKvIzKXXB3+19vcT2ga5Qq2l3TiPtOGsppRb2XrNs9qKdxIYvHmXo/9QP1V3SRW0XoD7ez8FpFabp42cmPOxUNk3FK3paQZABLxH5pzCWI9PzIAVfPDrm+sdnbgG7vAnwfL2IMMJSA3aDYGCbF9EgefG+STcpfqq7fQ6f5TBgLFwKBgCd7gn1xYL696SaKVSm7VngpXlczHVEpz3kStWR5gfzriPBxXgMVcWmcbajRser7ARpCEfbxM1UJyv6oAYZWVSNErNzNVb4POqLYcCNySuC6xKhs9FrEQnyKjyk8wI4VnrEMGrQ8e+qYSwYk9Gh6dKGoRMAPYVXQAO0fIsHF/T0a" ciphertext_b64 = "VocBRhpMmQ2XCzVehWSqheQLnU889gf3dhU4AnVnQTJjsKx/CM23qKDPkZDd2A/BnQsp99SN7ksIX5Raj0TPwyN5OCN/YrNFNGoOFlTsGhgP/hyE8X3Duiq6sNO0SMvRYNPFFGlJFsp1Fw3Z94eYMg4/Wpw5s4+Jo5Zm/qY7aTJIqDKDQ3CNHLeJgcMUOc9sz01/GzoUYKDVODHSxrYEk5ireFJFz9vP8P7Ha+VDUZuQIQdXer9NBbGFtYmWprY3nn4D3Dw93Sn0V0dIqYeIo91oKyslvMebmUM95S2PyIJdEpPb2DJDxjvX/0LLwSWlSXRWy9gapWoBkb4ynqZBsg==" - value = b'data to sign' + value = b"data to sign" - with MongoCryptBinaryIn(b'1' * 256) as output, \ - MongoCryptBinaryIn(base64.b64decode(key_b64)) as key,\ - MongoCryptBinaryIn(value) as value: + with MongoCryptBinaryIn(b"1" * 256) as output, MongoCryptBinaryIn( + base64.b64decode(key_b64) + ) as key, MongoCryptBinaryIn(value) as value: retval = sign_rsaes_pkcs1_v1_5( - ffi.NULL, key.bin, value.bin, output.bin, - lib.mongocrypt_status_new()) + ffi.NULL, key.bin, value.bin, output.bin, lib.mongocrypt_status_new() + ) self.assertTrue(retval) - self.assertEqual( - output.to_bytes(), base64.b64decode(ciphertext_b64)) + self.assertEqual(output.to_bytes(), base64.b64decode(ciphertext_b64)) if __name__ == "__main__": diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py b/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py index 3acea1c..d492442 100644 --- a/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py @@ -16,101 +16,117 @@ import base64 import copy -import json import os import sys import bson -from bson.raw_bson import RawBSONDocument +import httpx from bson import json_util from bson.binary import Binary, UuidRepresentation from bson.codec_options import CodecOptions from bson.json_util import JSONOptions +from bson.raw_bson import RawBSONDocument from bson.son import SON +import pymongocrypt.mongocrypt +from pymongocrypt.binary import MongoCryptBinaryIn, MongoCryptBinaryOut +from pymongocrypt.options import MongoCryptOptions + sys.path[0:0] = [""] -import pymongocrypt.mongocrypt +import unittest +import unittest.mock + +import respx from pymongo_auth_aws.auth import AwsCredential -from pymongocrypt.auto_encrypter import AutoEncrypter + +from pymongocrypt.asynchronous.auto_encrypter import AsyncAutoEncrypter +from pymongocrypt.asynchronous.explicit_encrypter import AsyncExplicitEncrypter +from pymongocrypt.asynchronous.state_machine import AsyncMongoCryptCallback from pymongocrypt.binding import lib -from pymongocrypt.compat import unicode_type, PY3 +from pymongocrypt.compat import PY3, unicode_type from pymongocrypt.errors import MongoCryptError -from pymongocrypt.explicit_encrypter import ExplicitEncrypter -from pymongocrypt.mongocrypt import (MongoCrypt, - MongoCryptBinaryIn, - MongoCryptBinaryOut, - MongoCryptOptions) -from pymongocrypt.state_machine import MongoCryptCallback - -from test import unittest, mock - -import requests.exceptions -import requests_mock - +from pymongocrypt.mongocrypt import MongoCrypt +from pymongocrypt.synchronous.auto_encrypter import AutoEncrypter +from pymongocrypt.synchronous.explicit_encrypter import ExplicitEncrypter +from pymongocrypt.synchronous.state_machine import MongoCryptCallback # Data for testing libbmongocrypt binding. -DATA_DIR = os.path.realpath(os.path.join(os.path.dirname(__file__), 'data')) +DATA_DIR = os.path.realpath(os.path.join(os.path.dirname(__file__), "data")) def to_base64(data): b64 = base64.b64encode(data) if not PY3: return unicode_type(b64) - return b64.decode('utf-8') + return b64.decode("utf-8") class TestMongoCryptBinary(unittest.TestCase): - def test_mongocrypt_binary_in(self): - with MongoCryptBinaryIn(b'1\x0023') as binary: + with MongoCryptBinaryIn(b"1\x0023") as binary: self.assertIsNotNone(binary.bin) - self.assertEqual(binary.to_bytes(), b'1\x0023') + self.assertEqual(binary.to_bytes(), b"1\x0023") self.assertIsNone(binary.bin) - with MongoCryptBinaryIn(b'') as binary: + with MongoCryptBinaryIn(b"") as binary: self.assertIsNotNone(binary.bin) - self.assertEqual(binary.to_bytes(), b'') + self.assertEqual(binary.to_bytes(), b"") self.assertIsNone(binary.bin) # Memoryview - with MongoCryptBinaryIn(memoryview(b'1\x0023')) as binary: + with MongoCryptBinaryIn(memoryview(b"1\x0023")) as binary: self.assertIsNotNone(binary.bin) - self.assertEqual(binary.to_bytes(), b'1\x0023') + self.assertEqual(binary.to_bytes(), b"1\x0023") self.assertIsNone(binary.bin) def test_mongocrypt_binary_out(self): with MongoCryptBinaryOut() as binary: self.assertIsNotNone(binary.bin) - self.assertEqual(binary.to_bytes(), b'') + self.assertEqual(binary.to_bytes(), b"") self.assertIsNone(binary.bin) class TestMongoCryptOptions(unittest.TestCase): - def test_mongocrypt_options(self): - schema_map = bson_data('schema-map.json') + schema_map = bson_data("schema-map.json") valid = [ - ({'local': {'key': b'1' * 96}}, None), - ({ 'aws' : {} }, schema_map), - ({'aws': {'accessKeyId': '', 'secretAccessKey': ''}}, schema_map), - ({'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo'}}, None), - ({'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo', - 'sessionToken': 'token'}}, None), - ({'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo'}, - 'local': {'key': b'1' * 96}}, None), - ({'local': {'key': to_base64(b'1' * 96)}}, None), - ({'local': {'key': Binary(b'1' * 96)}}, None), - ({'azure': {}}, None), - ({'azure': {'clientId': 'foo', 'clientSecret': 'bar'}}, None), - ({'gcp': {}}, None), - ({'gcp': {'email': 'foo@bar.baz', - 'privateKey': b'1'}}, None), - ({'gcp': {'email': 'foo@bar.baz', - 'privateKey': to_base64(b'1')}}, None), - ({'gcp': {'email': 'foo@bar.baz', - 'privateKey': Binary(b'1')}}, None) + ({"local": {"key": b"1" * 96}}, None), + ({"aws": {}}, schema_map), + ({"aws": {"accessKeyId": "", "secretAccessKey": ""}}, schema_map), + ({"aws": {"accessKeyId": "foo", "secretAccessKey": "foo"}}, None), + ( + { + "aws": { + "accessKeyId": "foo", + "secretAccessKey": "foo", + "sessionToken": "token", + } + }, + None, + ), + ( + { + "aws": {"accessKeyId": "foo", "secretAccessKey": "foo"}, + "local": {"key": b"1" * 96}, + }, + None, + ), + ({"local": {"key": to_base64(b"1" * 96)}}, None), + ({"local": {"key": Binary(b"1" * 96)}}, None), + ({"azure": {}}, None), + ({"azure": {"clientId": "foo", "clientSecret": "bar"}}, None), + ({"gcp": {}}, None), + ({"gcp": {"email": "foo@bar.baz", "privateKey": b"1"}}, None), + ({"gcp": {"email": "foo@bar.baz", "privateKey": to_base64(b"1")}}, None), + ({"gcp": {"email": "foo@bar.baz", "privateKey": Binary(b"1")}}, None), + ({"kmip": {"endpoint": "localhost"}}, None), ] + # Add tests for named KMS providers. + for kms_providers, schema_map in valid: + for name, val in list(kms_providers.items()): + kms_providers[f"{name}:named"] = val + for kms_providers, schema_map in valid: opts = MongoCryptOptions(kms_providers, schema_map) self.assertEqual(opts.kms_providers, kms_providers, msg=kms_providers) @@ -118,40 +134,63 @@ def test_mongocrypt_options(self): self.assertIsNone(opts.encrypted_fields_map) self.assertFalse(opts.bypass_query_analysis) - encrypted_fields_map = bson_data('encrypted-field-config-map.json') - opts = MongoCryptOptions(valid[0][0], schema_map, encrypted_fields_map=encrypted_fields_map, - bypass_query_analysis=True) + encrypted_fields_map = bson_data("encrypted-field-config-map.json") + opts = MongoCryptOptions( + valid[0][0], + schema_map, + encrypted_fields_map=encrypted_fields_map, + bypass_query_analysis=True, + ) self.assertEqual(opts.encrypted_fields_map, encrypted_fields_map) self.assertTrue(opts.bypass_query_analysis) def test_mongocrypt_options_validation(self): with self.assertRaisesRegex( - ValueError, 'at least one KMS provider must be configured'): + ValueError, "at least one KMS provider must be configured" + ): MongoCryptOptions({}) for invalid_kms_providers in [ - {'aws': {'accessKeyId': 'foo'}}, - {'aws': {'secretAccessKey': 'foo'}}]: + {"aws": {"accessKeyId": "foo"}}, + {"aws": {"secretAccessKey": "foo"}}, + {"aws:foo": {"accessKeyId": "foo"}}, + {"aws:foo": {"secretAccessKey": "foo"}}, + ]: + name = next(iter(invalid_kms_providers)) with self.assertRaisesRegex( - ValueError, r"kms_providers\['aws'\] must contain " - "'accessKeyId' and 'secretAccessKey'"): + ValueError, + rf"kms_providers\[{name!r}\] must contain " + "'accessKeyId' and 'secretAccessKey'", + ): MongoCryptOptions(invalid_kms_providers) with self.assertRaisesRegex( - TypeError, r"kms_providers\['local'\]\['key'\] must be an " - r"instance of bytes or str"): - MongoCryptOptions({'local': {'key': None}}) + TypeError, + r"kms_providers\['local'\]\['key'\] must be an " + r"instance of bytes or str", + ): + MongoCryptOptions({"local": {"key": None}}) with self.assertRaisesRegex( - TypeError, r"kms_providers\['gcp'\]\['privateKey'\] must be an " - r"instance of bytes or str"): - MongoCryptOptions({'gcp': {'email': "foo@bar.baz", - "privateKey": None}}) - - valid_kms = {'aws': {'accessKeyId': '', 'secretAccessKey': ''}} + TypeError, + r"kms_providers\['gcp'\]\['privateKey'\] must be an " + r"instance of bytes or str", + ): + MongoCryptOptions({"gcp": {"email": "foo@bar.baz", "privateKey": None}}) with self.assertRaisesRegex( - TypeError, "schema_map must be bytes or None"): + ValueError, r"kms_providers\['kmip'\] must contain 'endpoint'" + ): + MongoCryptOptions({"kmip": {}}) + with self.assertRaisesRegex( + TypeError, + r"kms_providers\['kmip'\]\['endpoint'\] must be an instance of str", + ): + MongoCryptOptions({"kmip": {"endpoint": None}}) + + valid_kms = {"aws": {"accessKeyId": "", "secretAccessKey": ""}} + with self.assertRaisesRegex(TypeError, "schema_map must be bytes or None"): MongoCryptOptions(valid_kms, schema_map={}) with self.assertRaisesRegex( - TypeError, "encrypted_fields_map must be bytes or None"): + TypeError, "encrypted_fields_map must be bytes or None" + ): MongoCryptOptions(valid_kms, encrypted_fields_map={}) @@ -159,8 +198,7 @@ class TestMongoCrypt(unittest.TestCase): maxDiff = None def test_mongocrypt(self): - kms_providers = { - 'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo'}} + kms_providers = {"aws": {"accessKeyId": "foo", "secretAccessKey": "foo"}} opts = MongoCryptOptions(kms_providers) mc = MongoCrypt(opts, MockCallback()) mc.close() @@ -168,85 +206,96 @@ def test_mongocrypt(self): def test_mongocrypt_aws_session_token(self): kms_providers = { - 'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'foo', - 'sessionToken': 'token'}} + "aws": { + "accessKeyId": "foo", + "secretAccessKey": "foo", + "sessionToken": "token", + } + } opts = MongoCryptOptions(kms_providers) mc = MongoCrypt(opts, MockCallback()) mc.close() def test_mongocrypt_validation(self): callback = MockCallback() - options = MongoCryptOptions({'local': {'key': b'\x00' * 96}}) + options = MongoCryptOptions({"local": {"key": b"\x00" * 96}}) - with self.assertRaisesRegex( - TypeError, 'options must be a MongoCryptOptions'): + with self.assertRaisesRegex(TypeError, "options must be a MongoCryptOptions"): MongoCrypt({}, callback) - with self.assertRaisesRegex( - TypeError, 'options must be a MongoCryptOptions'): + with self.assertRaisesRegex(TypeError, "options must be a MongoCryptOptions"): MongoCrypt(None, callback) with self.assertRaisesRegex( - TypeError, 'callback must be a MongoCryptCallback'): + TypeError, + "callback must be a MongoCryptCallback or AsyncMongoCryptCallback", + ): MongoCrypt(options, {}) with self.assertRaisesRegex( - TypeError, 'callback must be a MongoCryptCallback'): + TypeError, + "callback must be a MongoCryptCallback or AsyncMongoCryptCallback", + ): MongoCrypt(options, None) - invalid_key_len_opts = MongoCryptOptions({'local': {'key': b'1'}}) - with self.assertRaisesRegex( - MongoCryptError, "local key must be 96 bytes"): + invalid_key_len_opts = MongoCryptOptions({"local": {"key": b"1"}}) + with self.assertRaisesRegex(MongoCryptError, "local key must be 96 bytes"): MongoCrypt(invalid_key_len_opts, callback) def test_setopt_kms_provider_base64_or_bytes(self): test_fields = [("local", "key"), ("gcp", "privateKey")] callback = MockCallback() - base_kms_dict = {'local': {'key': b'\x00' * 96}, - 'gcp': {'email': 'foo@bar.baz', - 'privateKey': b'\x00'}} + base_kms_dict = { + "local": {"key": b"\x00" * 96}, + "gcp": {"email": "foo@bar.baz", "privateKey": b"\x00"}, + } for f1, f2 in test_fields: kms_dict = copy.deepcopy(base_kms_dict) # Case 1: pass key as string containing bytes (valid) - kms_dict[f1][f2] = b'\x00' * 96 + kms_dict[f1][f2] = b"\x00" * 96 options = MongoCryptOptions(kms_dict) mc = MongoCrypt(options, callback) mc.close() # Case 2: pass key as base64-encoded unicode literal (valid) - kms_dict[f1][f2] = to_base64(b'\x00' * 96) + kms_dict[f1][f2] = to_base64(b"\x00" * 96) options = MongoCryptOptions(kms_dict) mc = MongoCrypt(options, callback) mc.close() # Case 3: pass key as unicode string containing bytes (invalid) - kms_dict[f1][f2] = unicode_type(b'\x00' * 96) + kms_dict[f1][f2] = unicode_type(b"\x00" * 96) options = MongoCryptOptions(kms_dict) with self.assertRaisesRegex( - MongoCryptError, - "unable to parse base64 from UTF-8 field %s.%s" % ( - f1, f2)): + MongoCryptError, "unable to parse base64 from UTF-8 field" + ): MongoCrypt(options, callback) # Case 4: pass key as base64-encoded string (invalid) # Only applicable to "local" as key length is not validated for gcp. kms_dict = copy.deepcopy(base_kms_dict) - kms_dict['local']['key'] = base64.b64encode(b'\x00' * 96) + kms_dict["local"]["key"] = base64.b64encode(b"\x00" * 96) options = MongoCryptOptions(kms_dict) - with self.assertRaisesRegex( - MongoCryptError, "local key must be 96 bytes"): + with self.assertRaisesRegex(MongoCryptError, "local key must be 96 bytes"): MongoCrypt(options, callback) @staticmethod def create_mongocrypt(**kwargs): - return MongoCrypt(MongoCryptOptions({ - 'aws': {'accessKeyId': 'example', 'secretAccessKey': 'example'}, - 'local': {'key': b'\x00'*96}}, **kwargs), MockCallback()) + return MongoCrypt( + MongoCryptOptions( + { + "aws": {"accessKeyId": "example", "secretAccessKey": "example"}, + "local": {"key": b"\x00" * 96}, + }, + **kwargs, + ), + MockCallback(), + ) def _test_kms_context(self, ctx): key_filter = ctx.mongo_operation() - self.assertEqual(key_filter, bson_data('key-filter.json')) - ctx.add_mongo_operation_result(bson_data('key-document.json')) + self.assertEqual(key_filter, bson_data("key-filter.json")) + ctx.add_mongo_operation_result(bson_data("key-document.json")) ctx.complete_mongo_operation() self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_KMS) @@ -258,7 +307,7 @@ def _test_kms_context(self, ctx): self.assertEqual(len(kms_ctx.message), 790) self.assertEqual(kms_ctx.bytes_needed, 1024) - kms_ctx.feed(http_data('kms-reply.txt')) + kms_ctx.feed(http_data("kms-reply.txt")) self.assertEqual(kms_ctx.bytes_needed, 0) self.assertEqual(kms_ctx.kms_provider, "aws") @@ -269,24 +318,26 @@ def test_encrypt(self): self.addCleanup(mc.close) if mc.crypt_shared_lib_version is not None: self.skipTest("this test must be skipped when crypt_shared is loaded") - with mc.encryption_context('text', bson_data('command.json')) as ctx: + with mc.encryption_context("text", bson_data("command.json")) as ctx: self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_COLLINFO) list_colls_filter = ctx.mongo_operation() - self.assertEqual(list_colls_filter, - bson_data('list-collections-filter.json')) + self.assertEqual( + list_colls_filter, bson_data("list-collections-filter.json") + ) - ctx.add_mongo_operation_result(bson_data('collection-info.json')) + ctx.add_mongo_operation_result(bson_data("collection-info.json")) ctx.complete_mongo_operation() self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_MARKINGS) mongocryptd_cmd = ctx.mongo_operation() - self.assertEqual(bson.decode(mongocryptd_cmd, OPTS), - json_data('mongocryptd-command.json')) - self.assertEqual(mongocryptd_cmd, - bson_data('mongocryptd-command.json')) + self.assertEqual( + bson.decode(mongocryptd_cmd, OPTS), + json_data("mongocryptd-command.json"), + ) + self.assertEqual(mongocryptd_cmd, bson_data("mongocryptd-command.json")) - ctx.add_mongo_operation_result(bson_data('mongocryptd-reply.json')) + ctx.add_mongo_operation_result(bson_data("mongocryptd-reply.json")) ctx.complete_mongo_operation() self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) @@ -295,16 +346,16 @@ def test_encrypt(self): self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_READY) encrypted = ctx.finish() - self.assertEqual(bson.decode(encrypted, OPTS), - json_data('encrypted-command.json')) - self.assertEqual(encrypted, bson_data('encrypted-command.json')) + self.assertEqual( + bson.decode(encrypted, OPTS), json_data("encrypted-command.json") + ) + self.assertEqual(encrypted, bson_data("encrypted-command.json")) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_DONE) def test_decrypt(self): mc = self.create_mongocrypt() self.addCleanup(mc.close) - with mc.decryption_context( - bson_data('encrypted-command-reply.json')) as ctx: + with mc.decryption_context(bson_data("encrypted-command-reply.json")) as ctx: self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) self._test_kms_context(ctx) @@ -312,46 +363,67 @@ def test_decrypt(self): self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_READY) encrypted = ctx.finish() - self.assertEqual(bson.decode(encrypted, OPTS), - json_data('command-reply.json')) - self.assertEqual(encrypted, bson_data('command-reply.json')) + self.assertEqual( + bson.decode(encrypted, OPTS), json_data("command-reply.json") + ) + self.assertEqual(encrypted, bson_data("command-reply.json")) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_DONE) def test_encrypt_encrypted_fields_map(self): - encrypted_fields_map = bson_data('compact/success/encrypted-field-config-map.json') + encrypted_fields_map = bson_data( + "compact/success/encrypted-field-config-map.json" + ) mc = self.create_mongocrypt(encrypted_fields_map=encrypted_fields_map) self.addCleanup(mc.close) - with mc.encryption_context('db', bson_data('compact/success/cmd.json')) as ctx: + with mc.encryption_context("db", bson_data("compact/success/cmd.json")) as ctx: self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) ctx.mongo_operation() - ctx.add_mongo_operation_result(bson_data( - 'keys/12345678123498761234123456789012-local-document.json')) + ctx.add_mongo_operation_result( + bson_data("keys/12345678123498761234123456789012-local-document.json") + ) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) ctx.mongo_operation() - ctx.add_mongo_operation_result(bson_data( - 'keys/ABCDEFAB123498761234123456789012-local-document.json')) + ctx.add_mongo_operation_result( + bson_data("keys/ABCDEFAB123498761234123456789012-local-document.json") + ) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_NEED_MONGO_KEYS) ctx.mongo_operation() - ctx.add_mongo_operation_result(bson_data( - 'keys/12345678123498761234123456789013-local-document.json')) + ctx.add_mongo_operation_result( + bson_data("keys/12345678123498761234123456789013-local-document.json") + ) ctx.complete_mongo_operation() self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_READY) encrypted = ctx.finish() - self.assertEqual(bson.decode(encrypted, OPTS), - json_data('compact/success/encrypted-payload.json')) - self.assertEqual(encrypted, bson_data('compact/success/encrypted-payload.json')) + self.assertEqual( + bson.decode(encrypted, OPTS), + json_data("compact/success/encrypted-payload.json"), + ) + self.assertEqual( + encrypted, bson_data("compact/success/encrypted-payload.json") + ) self.assertEqual(ctx.state, lib.MONGOCRYPT_CTX_DONE) + def test_pymongo_imports(self): + from pymongocrypt.auto_encrypter import AutoEncrypter # type:ignore[import] + from pymongocrypt.errors import MongoCryptError # type:ignore[import] + from pymongocrypt.explicit_encrypter import ( + ExplicitEncrypter, # type:ignore[import] + ) + from pymongocrypt.mongocrypt import MongoCryptOptions # type:ignore[import] + from pymongocrypt.state_machine import MongoCryptCallback # type:ignore[import] + class MockCallback(MongoCryptCallback): - def __init__(self, - list_colls_result=None, - mongocryptd_reply=None, - key_docs=None, - kms_reply=None): + def __init__( + self, + list_colls_result=None, + mongocryptd_reply=None, + key_docs=None, + kms_reply=None, + ): self.list_colls_result = list_colls_result self.mongocryptd_reply = mongocryptd_reply self.key_docs = key_docs @@ -381,108 +453,549 @@ def close(self): pass +class MockAsyncCallback(AsyncMongoCryptCallback): + def __init__( + self, + list_colls_result=None, + mongocryptd_reply=None, + key_docs=None, + kms_reply=None, + ): + self.list_colls_result = list_colls_result + self.mongocryptd_reply = mongocryptd_reply + self.key_docs = key_docs + self.kms_reply = kms_reply + self.kms_endpoint = None + + async def kms_request(self, kms_context): + self.kms_endpoint = kms_context.endpoint + kms_context.feed(self.kms_reply) + + async def collection_info(self, ns, filter): + return self.list_colls_result + + async def mark_command(self, ns, cmd): + return self.mongocryptd_reply + + async def fetch_keys(self, filter): + return self.key_docs + + async def insert_data_key(self, data_key): + raise NotImplementedError + + def bson_encode(self, doc): + return bson.encode(doc) + + async def close(self): + pass + + class TestMongoCryptCallback(unittest.TestCase): maxDiff = None @staticmethod def mongo_crypt_opts(): - return MongoCryptOptions({ - 'aws': {'accessKeyId': 'example', 'secretAccessKey': 'example'}, - 'local': {'key': b'\x00'*96}}) - - @unittest.skipUnless(os.getenv("TEST_CRYPT_SHARED"), "this test requires TEST_CRYPT_SHARED=1") + return MongoCryptOptions( + { + "aws": {"accessKeyId": "example", "secretAccessKey": "example"}, + "local": {"key": b"\x00" * 96}, + } + ) + + @unittest.skipUnless( + os.getenv("TEST_CRYPT_SHARED"), "this test requires TEST_CRYPT_SHARED=1" + ) def test_crypt_shared(self): kms_providers = { - 'aws': {'accessKeyId': 'example', 'secretAccessKey': 'example'}, - 'local': {'key': b'\x00'*96}} + "aws": {"accessKeyId": "example", "secretAccessKey": "example"}, + "local": {"key": b"\x00" * 96}, + } mc = MongoCrypt(MongoCryptOptions(kms_providers), MockCallback()) self.addCleanup(mc.close) self.assertIsNotNone(mc.crypt_shared_lib_version) # Test that we can pick up crypt_shared automatically - encrypter = AutoEncrypter(MockCallback(), MongoCryptOptions( - kms_providers, - bypass_encryption=False, - crypt_shared_lib_required=True)) + encrypter = AutoEncrypter( + MockCallback(), + MongoCryptOptions( + kms_providers, bypass_encryption=False, crypt_shared_lib_required=True + ), + ) self.addCleanup(encrypter.close) - encrypter = AutoEncrypter(MockCallback(), MongoCryptOptions( - kms_providers, - crypt_shared_lib_path=os.environ["CRYPT_SHARED_PATH"], - crypt_shared_lib_required=True)) + encrypter = AutoEncrypter( + MockCallback(), + MongoCryptOptions( + kms_providers, + crypt_shared_lib_path=os.environ["CRYPT_SHARED_PATH"], + crypt_shared_lib_required=True, + ), + ) self.addCleanup(encrypter.close) with self.assertRaisesRegex(MongoCryptError, "/doesnotexist"): - AutoEncrypter(MockCallback(), MongoCryptOptions( - kms_providers, - crypt_shared_lib_path="/doesnotexist", - crypt_shared_lib_required=True)) + AutoEncrypter( + MockCallback(), + MongoCryptOptions( + kms_providers, + crypt_shared_lib_path="/doesnotexist", + crypt_shared_lib_required=True, + ), + ) def test_encrypt(self): - encrypter = AutoEncrypter(MockCallback( - list_colls_result=bson_data('collection-info.json'), - mongocryptd_reply=bson_data('mongocryptd-reply.json'), - key_docs=[bson_data('key-document.json')], - kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) + encrypter = AutoEncrypter( + MockCallback( + list_colls_result=bson_data("collection-info.json"), + mongocryptd_reply=bson_data("mongocryptd-reply.json"), + key_docs=[bson_data("key-document.json")], + kms_reply=http_data("kms-reply.txt"), + ), + self.mongo_crypt_opts(), + ) self.addCleanup(encrypter.close) - encrypted = encrypter.encrypt('test', bson_data('command.json')) - self.assertEqual(bson.decode(encrypted, OPTS), - json_data('encrypted-command.json')) - self.assertEqual(encrypted, bson_data('encrypted-command.json')) + encrypted = encrypter.encrypt("test", bson_data("command.json")) + self.assertEqual( + bson.decode(encrypted, OPTS), json_data("encrypted-command.json") + ) + self.assertEqual(encrypted, bson_data("encrypted-command.json")) def test_decrypt(self): - encrypter = AutoEncrypter(MockCallback( - list_colls_result=bson_data('collection-info.json'), - mongocryptd_reply=bson_data('mongocryptd-reply.json'), - key_docs=[bson_data('key-document.json')], - kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) + encrypter = AutoEncrypter( + MockCallback( + list_colls_result=bson_data("collection-info.json"), + mongocryptd_reply=bson_data("mongocryptd-reply.json"), + key_docs=[bson_data("key-document.json")], + kms_reply=http_data("kms-reply.txt"), + ), + self.mongo_crypt_opts(), + ) self.addCleanup(encrypter.close) - decrypted = encrypter.decrypt( - bson_data('encrypted-command-reply.json')) - self.assertEqual(bson.decode(decrypted, OPTS), - json_data('command-reply.json')) - self.assertEqual(decrypted, bson_data('command-reply.json')) + decrypted = encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertEqual(bson.decode(decrypted, OPTS), json_data("command-reply.json")) + self.assertEqual(decrypted, bson_data("command-reply.json")) def test_need_kms_aws_credentials(self): - kms_providers = { 'aws': {} } + kms_providers = {"aws": {}} opts = MongoCryptOptions(kms_providers) callback = MockCallback( - list_colls_result=bson_data('collection-info.json'), - mongocryptd_reply=bson_data('mongocryptd-reply.json'), - key_docs=[bson_data('key-document.json')], - kms_reply=http_data('kms-reply.txt')) + list_colls_result=bson_data("collection-info.json"), + mongocryptd_reply=bson_data("mongocryptd-reply.json"), + key_docs=[bson_data("key-document.json")], + kms_reply=http_data("kms-reply.txt"), + ) encrypter = AutoEncrypter(callback, opts) self.addCleanup(encrypter.close) - with mock.patch("pymongocrypt.credentials.aws_temp_credentials") as m: + with unittest.mock.patch( + "pymongocrypt.synchronous.credentials.aws_temp_credentials" + ) as m: m.return_value = AwsCredential("example", "example", None) - decrypted = encrypter.decrypt( - bson_data('encrypted-command-reply.json')) + decrypted = encrypter.decrypt(bson_data("encrypted-command-reply.json")) self.assertTrue(m.called) - self.assertEqual(bson.decode(decrypted, OPTS), - json_data('command-reply.json')) - self.assertEqual(decrypted, bson_data('command-reply.json')) + self.assertEqual(bson.decode(decrypted, OPTS), json_data("command-reply.json")) + self.assertEqual(decrypted, bson_data("command-reply.json")) def test_need_kms_gcp_credentials(self): - kms_providers = { 'gcp': {} } + kms_providers = {"gcp": {}} opts = MongoCryptOptions(kms_providers) callback = MockCallback( - list_colls_result=bson_data('collection-info.json'), - mongocryptd_reply=bson_data('mongocryptd-reply.json'), - key_docs=[bson_data('key-document-gcp.json')], - kms_reply=http_data('kms-reply-gcp.txt')) + list_colls_result=bson_data("collection-info.json"), + mongocryptd_reply=bson_data("mongocryptd-reply.json"), + key_docs=[bson_data("key-document-gcp.json")], + kms_reply=http_data("kms-reply-gcp.txt"), + ) encrypter = AutoEncrypter(callback, opts) self.addCleanup(encrypter.close) - with requests_mock.Mocker() as m: + with respx.mock() as router: data = {"access_token": "foo"} url = "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" - m.get(url, text=json.dumps(data)) - decrypted = encrypter.decrypt( - bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) - - self.assertEqual(bson.decode(decrypted, OPTS), - json_data('command-reply.json')) - self.assertEqual(decrypted, bson_data('command-reply.json')) + router.add( + respx.get(url=url).mock(return_value=httpx.Response(200, json=data)) + ) + decrypted = encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) + + self.assertEqual(bson.decode(decrypted, OPTS), json_data("command-reply.json")) + self.assertEqual(decrypted, bson_data("command-reply.json")) + + +if sys.version_info >= (3, 8, 0): # noqa: UP036 + + class TestAsyncMongoCryptCallback(unittest.IsolatedAsyncioTestCase): + maxDiff = None + + @staticmethod + def mongo_crypt_opts(): + return MongoCryptOptions( + { + "aws": {"accessKeyId": "example", "secretAccessKey": "example"}, + "local": {"key": b"\x00" * 96}, + } + ) + + @unittest.skipUnless( + os.getenv("TEST_CRYPT_SHARED"), "this test requires TEST_CRYPT_SHARED=1" + ) + async def test_crypt_shared(self): + kms_providers = { + "aws": {"accessKeyId": "example", "secretAccessKey": "example"}, + "local": {"key": b"\x00" * 96}, + } + mc = MongoCrypt(MongoCryptOptions(kms_providers), MockAsyncCallback()) + self.addCleanup(mc.close) + self.assertIsNotNone(mc.crypt_shared_lib_version) + # Test that we can pick up crypt_shared automatically + encrypter = AsyncAutoEncrypter( + MockAsyncCallback(), + MongoCryptOptions( + kms_providers, + bypass_encryption=False, + crypt_shared_lib_required=True, + ), + ) + self.addAsyncCleanup(encrypter.close) + encrypter = AsyncAutoEncrypter( + MockAsyncCallback(), + MongoCryptOptions( + kms_providers, + crypt_shared_lib_path=os.environ["CRYPT_SHARED_PATH"], + crypt_shared_lib_required=True, + ), + ) + self.addAsyncCleanup(encrypter.close) + with self.assertRaisesRegex(MongoCryptError, "/doesnotexist"): + AsyncAutoEncrypter( + MockAsyncCallback(), + MongoCryptOptions( + kms_providers, + crypt_shared_lib_path="/doesnotexist", + crypt_shared_lib_required=True, + ), + ) + + async def test_encrypt(self): + encrypter = AsyncAutoEncrypter( + MockAsyncCallback( + list_colls_result=bson_data("collection-info.json"), + mongocryptd_reply=bson_data("mongocryptd-reply.json"), + key_docs=[bson_data("key-document.json")], + kms_reply=http_data("kms-reply.txt"), + ), + self.mongo_crypt_opts(), + ) + self.addAsyncCleanup(encrypter.close) + encrypted = await encrypter.encrypt("test", bson_data("command.json")) + self.assertEqual( + bson.decode(encrypted, OPTS), json_data("encrypted-command.json") + ) + self.assertEqual(encrypted, bson_data("encrypted-command.json")) + + async def test_decrypt(self): + encrypter = AsyncAutoEncrypter( + MockAsyncCallback( + list_colls_result=bson_data("collection-info.json"), + mongocryptd_reply=bson_data("mongocryptd-reply.json"), + key_docs=[bson_data("key-document.json")], + kms_reply=http_data("kms-reply.txt"), + ), + self.mongo_crypt_opts(), + ) + self.addAsyncCleanup(encrypter.close) + decrypted = await encrypter.decrypt( + bson_data("encrypted-command-reply.json") + ) + self.assertEqual( + bson.decode(decrypted, OPTS), json_data("command-reply.json") + ) + self.assertEqual(decrypted, bson_data("command-reply.json")) + + async def test_need_kms_aws_credentials(self): + kms_providers = {"aws": {}} + opts = MongoCryptOptions(kms_providers) + callback = MockAsyncCallback( + list_colls_result=bson_data("collection-info.json"), + mongocryptd_reply=bson_data("mongocryptd-reply.json"), + key_docs=[bson_data("key-document.json")], + kms_reply=http_data("kms-reply.txt"), + ) + encrypter = AsyncAutoEncrypter(callback, opts) + self.addAsyncCleanup(encrypter.close) + + with unittest.mock.patch( + "pymongocrypt.asynchronous.credentials.aws_temp_credentials" + ) as m: + m.return_value = AwsCredential("example", "example", None) + decrypted = await encrypter.decrypt( + bson_data("encrypted-command-reply.json") + ) + self.assertTrue(m.called) + + self.assertEqual( + bson.decode(decrypted, OPTS), json_data("command-reply.json") + ) + self.assertEqual(decrypted, bson_data("command-reply.json")) + + async def test_need_kms_gcp_credentials(self): + kms_providers = {"gcp": {}} + opts = MongoCryptOptions(kms_providers) + callback = MockAsyncCallback( + list_colls_result=bson_data("collection-info.json"), + mongocryptd_reply=bson_data("mongocryptd-reply.json"), + key_docs=[bson_data("key-document-gcp.json")], + kms_reply=http_data("kms-reply-gcp.txt"), + ) + encrypter = AsyncAutoEncrypter(callback, opts) + self.addAsyncCleanup(encrypter.close) + + with respx.mock() as router: + data = {"access_token": "foo"} + url = "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" + router.add( + respx.get(url=url).mock(return_value=httpx.Response(200, json=data)) + ) + decrypted = await encrypter.decrypt( + bson_data("encrypted-command-reply.json") + ) + self.assertTrue(len(router.calls)) + + self.assertEqual( + bson.decode(decrypted, OPTS), json_data("command-reply.json") + ) + self.assertEqual(decrypted, bson_data("command-reply.json")) + + class TestAsyncExplicitEncryption(unittest.IsolatedAsyncioTestCase): + maxDiff = None + + @staticmethod + def mongo_crypt_opts(): + return MongoCryptOptions( + { + "aws": {"accessKeyId": "example", "secretAccessKey": "example"}, + "local": {"key": b"\x00" * 96}, + } + ) + + async def _test_encrypt_decrypt(self, key_id=None, key_alt_name=None): + encrypter = AsyncExplicitEncrypter( + MockAsyncCallback( + key_docs=[bson_data("key-document.json")], + kms_reply=http_data("kms-reply.txt"), + ), + self.mongo_crypt_opts(), + ) + self.addCleanup(encrypter.close) + + val = {"v": "hello"} + encoded_val = bson.encode(val) + algo = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + encrypted = await encrypter.encrypt( + encoded_val, algo, key_id=key_id, key_alt_name=key_alt_name + ) + self.assertEqual( + bson.decode(encrypted, OPTS), json_data("encrypted-value.json") + ) + self.assertEqual(encrypted, bson_data("encrypted-value.json")) + + decrypted = await encrypter.decrypt(encrypted) + self.assertEqual(bson.decode(decrypted, OPTS), val) + self.assertEqual(encoded_val, decrypted) + + async def test_encrypt_decrypt(self): + key_id = json_data("key-document.json")["_id"] + await self._test_encrypt_decrypt(key_id=key_id) + + async def test_encrypt_decrypt_key_alt_name(self): + key_alt_name = json_data("key-document.json")["keyAltNames"][0] + await self._test_encrypt_decrypt(key_alt_name=key_alt_name) + + async def test_encrypt_errors(self): + key_id = json_data("key-document.json")["_id"] + encrypter = AsyncExplicitEncrypter( + MockAsyncCallback(key_docs=[]), self.mongo_crypt_opts() + ) + self.addCleanup(encrypter.close) + + val = {"v": "value123"} + encoded_val = bson.encode(val) + # Invalid algorithm. + with self.assertRaisesRegex(MongoCryptError, "algorithm"): + await encrypter.encrypt(encoded_val, "Invalid", key_id) + # Invalid query_type type. + with self.assertRaisesRegex(TypeError, "query_type"): + await encrypter.encrypt(encoded_val, "Indexed", key_id, query_type=42) + # Invalid query_type string. + with self.assertRaisesRegex(MongoCryptError, "query_type"): + await encrypter.encrypt( + encoded_val, + "Indexed", + key_id, + query_type="invalid query type string", + ) + # Invalid contention_factor type. + with self.assertRaisesRegex(TypeError, "contention_factor"): + await encrypter.encrypt( + encoded_val, "Indexed", key_id, contention_factor="not an int" + ) + with self.assertRaisesRegex(MongoCryptError, "contention"): + await encrypter.encrypt( + encoded_val, "Indexed", key_id, contention_factor=-1 + ) + # Invalid: Unindexed + query_type is an error. + with self.assertRaisesRegex(MongoCryptError, "query"): + await encrypter.encrypt( + encoded_val, "Unindexed", key_id, query_type="equality" + ) + # Invalid: Unindexed + contention_factor is an error. + with self.assertRaisesRegex(MongoCryptError, "contention"): + await encrypter.encrypt( + encoded_val, "Unindexed", key_id, contention_factor=1 + ) + + async def test_encrypt_indexed(self): + key_path = "keys/ABCDEFAB123498761234123456789012-local-document.json" + key_id = json_data(key_path)["_id"] + encrypter = AsyncExplicitEncrypter( + MockAsyncCallback( + key_docs=[bson_data(key_path)], kms_reply=http_data("kms-reply.txt") + ), + self.mongo_crypt_opts(), + ) + self.addCleanup(encrypter.close) + + val = {"v": "value123"} + encoded_val = bson.encode(val) + for kwargs in [ + dict(algorithm="Indexed", contention_factor=0), + dict(algorithm="Indexed", query_type="equality", contention_factor=0), + dict(algorithm="Indexed", contention_factor=100), + dict(algorithm="Unindexed"), + ]: + kwargs["key_id"] = key_id + encrypted = await encrypter.encrypt(encoded_val, **kwargs) + encrypted_val = bson.decode(encrypted, OPTS)["v"] + self.assertIsInstance(encrypted_val, Binary) + self.assertEqual(encrypted_val.subtype, 6) + + # Queryable Encryption find payloads cannot be round-tripped. + if "query_type" not in kwargs: + decrypted = await encrypter.decrypt(encrypted) + self.assertEqual(bson.decode(decrypted, OPTS), val) + self.assertEqual(encoded_val, decrypted) + + async def test_data_key_creation(self): + mock_key_vault = AsyncKeyVaultCallback( + kms_reply=http_data("kms-encrypt-reply.txt") + ) + opts = MongoCryptOptions( + { + "aws": {"accessKeyId": "example", "secretAccessKey": "example"}, + "aws:named": { + "accessKeyId": "example", + "secretAccessKey": "example", + }, + "local": {"key": b"\x00" * 96}, + "local:named": {"key": b"\x01" * 96}, + } + ) + encrypter = AsyncExplicitEncrypter(mock_key_vault, opts) + self.addCleanup(encrypter.close) + + valid_args = [ + ("local", None, ["first", "second"]), + ("local:named", None, ["local:named"]), + ("aws", {"region": "region", "key": "cmk"}, ["third", "forth"]), + ("aws:named", {"region": "region", "key": "cmk"}, ["aws:named"]), + # Unicode region and key + ("aws", {"region": "region-unicode", "key": "cmk-unicode"}, []), + # Endpoint + ( + "aws", + { + "region": "region", + "key": "cmk", + "endpoint": "kms.us-east-1.amazonaws.com:443", + }, + [], + ), + ] + for kms_provider, master_key, key_alt_names in valid_args: + key_id = await encrypter.create_data_key( + kms_provider, master_key=master_key, key_alt_names=key_alt_names + ) + self.assertIsInstance(key_id, Binary) + self.assertEqual(key_id.subtype, 4) + data_key = bson.decode(mock_key_vault.data_key, OPTS) + # CDRIVER-3277 The order of key_alt_names is not maintained. + for name in key_alt_names: + self.assertIn(name, data_key["keyAltNames"]) + + # Assert that the custom endpoint is passed to libmongocrypt. + master_key = {"region": "region", "key": "key", "endpoint": "example.com"} + key_material = base64.b64decode( + "xPTAjBRG5JiPm+d3fj6XLi2q5DMXUS/f1f+SMAlhhwkhDRL0kr8r9GDLIGTAGlvC+HVjSIgdL+RKwZCvpXSyxTICWSXTUYsWYPyu3IoHbuBZdmw2faM3WhcRIgbMReU5" + ) + if not PY3: + key_material = Binary(key_material) + await encrypter.create_data_key( + "aws", master_key=master_key, key_material=key_material + ) + self.assertEqual("example.com:443", mock_key_vault.kms_endpoint) + + async def test_data_key_creation_bad_key_material(self): + mock_key_vault = AsyncKeyVaultCallback( + kms_reply=http_data("kms-encrypt-reply.txt") + ) + encrypter = AsyncExplicitEncrypter(mock_key_vault, self.mongo_crypt_opts()) + self.addCleanup(encrypter.close) + + key_material = Binary(b"0" * 97) + with self.assertRaisesRegex( + MongoCryptError, "keyMaterial should have length 96, but has length 97" + ): + await encrypter.create_data_key("local", key_material=key_material) + + async def test_rewrap_many_data_key(self): + key_path = "keys/ABCDEFAB123498761234123456789012-local-document.json" + key_path2 = "keys/12345678123498761234123456789012-local-document.json" + encrypter = AsyncExplicitEncrypter( + MockAsyncCallback(key_docs=[bson_data(key_path), bson_data(key_path2)]), + self.mongo_crypt_opts(), + ) + self.addCleanup(encrypter.close) + + result = await encrypter.rewrap_many_data_key({}) + raw_doc = RawBSONDocument(result) + assert len(raw_doc["v"]) == 2 + + async def test_range_query_int32(self): + key_path = "keys/ABCDEFAB123498761234123456789012-local-document.json" + key_id = json_data(key_path)["_id"] + encrypter = AsyncExplicitEncrypter( + MockAsyncCallback( + key_docs=[bson_data(key_path)], kms_reply=http_data("kms-reply.txt") + ), + self.mongo_crypt_opts(), + ) + self.addCleanup(encrypter.close) + + range_opts = bson_data("fle2-find-range-explicit-v2/int32/rangeopts.json") + value = bson_data("fle2-find-range-explicit-v2/int32/value-to-encrypt.json") + expected = json_data( + "fle2-find-range-explicit-v2/int32/encrypted-payload.json" + ) + encrypted = await encrypter.encrypt( + value, + "range", + key_id=key_id, + query_type="range", + contention_factor=4, + range_opts=range_opts, + is_expression=True, + ) + encrypted_val = bson.decode(encrypted, OPTS) + self.assertEqual( + encrypted_val, adjust_range_counter(encrypted_val, expected) + ) class TestNeedKMSAzureCredentials(unittest.TestCase): @@ -490,129 +1003,156 @@ class TestNeedKMSAzureCredentials(unittest.TestCase): def get_encrypter(self, clear_cache=True): if clear_cache: - pymongocrypt.credentials._azure_creds_cache = None - kms_providers = { 'azure': {} } + pymongocrypt.synchronous.credentials._azure_creds_cache = None + kms_providers = {"azure": {}} opts = MongoCryptOptions(kms_providers) callback = MockCallback( - list_colls_result=bson_data('collection-info.json'), - mongocryptd_reply=bson_data('mongocryptd-reply.json'), - key_docs=[bson_data('key-document-azure.json')], - kms_reply=http_data('kms-reply-azure.txt')) + list_colls_result=bson_data("collection-info.json"), + mongocryptd_reply=bson_data("mongocryptd-reply.json"), + key_docs=[bson_data("key-document-azure.json")], + kms_reply=http_data("kms-reply-azure.txt"), + ) encrypter = AutoEncrypter(callback, opts) self.addCleanup(encrypter.close) return encrypter def test_success(self): encrypter = self.get_encrypter() - with requests_mock.Mocker() as m: + with respx.mock() as router: data = {"access_token": "foo", "expires_in": 4000} url = "http://169.254.169.254/metadata/identity/oauth2/token" - m.get(url, text=json.dumps(data)) - decrypted = encrypter.decrypt( - bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) + router.add( + respx.get(url=url).mock(return_value=httpx.Response(200, json=data)) + ) + decrypted = encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) - self.assertEqual(bson.decode(decrypted, OPTS), - json_data('command-reply.json')) - self.assertEqual(decrypted, bson_data('command-reply.json')) - self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) + self.assertEqual(bson.decode(decrypted, OPTS), json_data("command-reply.json")) + self.assertEqual(decrypted, bson_data("command-reply.json")) + self.assertIsNotNone(pymongocrypt.synchronous.credentials._azure_creds_cache) def test_empty_json(self): encrypter = self.get_encrypter() - with requests_mock.Mocker() as m: + with respx.mock() as router: url = "http://169.254.169.254/metadata/identity/oauth2/token" - m.get(url, text=json.dumps({})) - with self.assertRaisesRegex(MongoCryptError, "Azure IMDS response must contain"): - encrypter.decrypt(bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) - self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) + router.add( + respx.get(url=url).mock(return_value=httpx.Response(200, json={})) + ) + with self.assertRaisesRegex( + MongoCryptError, "Azure IMDS response must contain" + ): + encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) + self.assertIsNone(pymongocrypt.synchronous.credentials._azure_creds_cache) def test_bad_json(self): encrypter = self.get_encrypter() - with requests_mock.Mocker() as m: + with respx.mock() as router: url = "http://169.254.169.254/metadata/identity/oauth2/token" - m.get(url, text="a'") - with self.assertRaisesRegex(MongoCryptError, "Azure IMDS response must be in JSON format"): - encrypter.decrypt(bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) - self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) + router.add( + respx.get(url=url).mock(return_value=httpx.Response(200, text="a'")) + ) + with self.assertRaisesRegex( + MongoCryptError, "Azure IMDS response must be in JSON format" + ): + encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) + self.assertIsNone(pymongocrypt.synchronous.credentials._azure_creds_cache) def test_http_404(self): encrypter = self.get_encrypter() - with requests_mock.Mocker() as m: + with respx.mock() as router: url = "http://169.254.169.254/metadata/identity/oauth2/token" - m.get(url, status_code=404) - with self.assertRaisesRegex(MongoCryptError, "Failed to acquire IMDS access token."): - encrypter.decrypt(bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) - self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) + router.add(respx.get(url=url).mock(return_value=httpx.Response(404))) + with self.assertRaisesRegex( + MongoCryptError, "Failed to acquire IMDS access token." + ): + encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) + self.assertIsNone(pymongocrypt.synchronous.credentials._azure_creds_cache) def test_http_500(self): encrypter = self.get_encrypter() - with requests_mock.Mocker() as m: + with respx.mock() as router: url = "http://169.254.169.254/metadata/identity/oauth2/token" - m.get(url, status_code=500) - with self.assertRaisesRegex(MongoCryptError, "Failed to acquire IMDS access token."): - encrypter.decrypt(bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) - self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) + router.add(respx.get(url=url).mock(return_value=httpx.Response(500))) + with self.assertRaisesRegex( + MongoCryptError, "Failed to acquire IMDS access token." + ): + encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) + self.assertIsNone(pymongocrypt.synchronous.credentials._azure_creds_cache) def test_slow_response(self): encrypter = self.get_encrypter() - with requests_mock.Mocker() as m: + with respx.mock() as router: url = "http://169.254.169.254/metadata/identity/oauth2/token" - m.get(url, exc=requests.exceptions.ConnectTimeout) - with self.assertRaisesRegex(MongoCryptError, "Failed to acquire IMDS access token: "): - encrypter.decrypt(bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) - self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) + router.add( + respx.get(url=url).mock(side_effect=httpx._exceptions.ConnectTimeout) + ) + with self.assertRaisesRegex( + MongoCryptError, "Failed to acquire IMDS access token: " + ): + encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) + self.assertIsNone(pymongocrypt.synchronous.credentials._azure_creds_cache) def test_cache(self): encrypter = self.get_encrypter() - with requests_mock.Mocker() as m: + with respx.mock() as router: data = {"access_token": "foo", "expires_in": 4000} url = "http://169.254.169.254/metadata/identity/oauth2/token" - m.get(url, text=json.dumps(data)) - decrypted = encrypter.decrypt( - bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) + router.add( + respx.get(url=url).mock( + return_value=httpx.Response(status_code=200, json=data) + ) + ) + encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) - self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) + self.assertIsNotNone(pymongocrypt.synchronous.credentials._azure_creds_cache) # Should use the cached value. - decrypted = encrypter.decrypt(bson_data('encrypted-command-reply.json')) - self.assertEqual(decrypted, bson_data('command-reply.json')) + decrypted = encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertEqual(decrypted, bson_data("command-reply.json")) - self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) + self.assertIsNotNone(pymongocrypt.synchronous.credentials._azure_creds_cache) def test_cache_expires_soon(self): encrypter = self.get_encrypter() - with requests_mock.Mocker() as m: + with respx.mock() as router: data = {"access_token": "foo", "expires_in": 10} url = "http://169.254.169.254/metadata/identity/oauth2/token" - m.get(url, text=json.dumps(data)) - decrypted = encrypter.decrypt( - bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) + router.add( + respx.get(url=url).mock( + return_value=httpx.Response(status_code=200, json=data) + ) + ) + encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) - self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) + self.assertIsNotNone(pymongocrypt.synchronous.credentials._azure_creds_cache) # Should not use the cached value. encrypter = self.get_encrypter(False) - self.assertIsNotNone(pymongocrypt.credentials._azure_creds_cache) - with requests_mock.Mocker() as m: + self.assertIsNotNone(pymongocrypt.synchronous.credentials._azure_creds_cache) + with respx.mock() as router: url = "http://169.254.169.254/metadata/identity/oauth2/token" - m.get(url, exc=requests.exceptions.ConnectTimeout) - with self.assertRaisesRegex(MongoCryptError, "Failed to acquire IMDS access token: "): - encrypter.decrypt(bson_data('encrypted-command-reply.json')) - self.assertTrue(m.called) + router.add( + respx.get(url=url).mock(side_effect=httpx._exceptions.ConnectTimeout) + ) + with self.assertRaisesRegex( + MongoCryptError, "Failed to acquire IMDS access token: " + ): + encrypter.decrypt(bson_data("encrypted-command-reply.json")) + self.assertTrue(len(router.calls)) - self.assertIsNone(pymongocrypt.credentials._azure_creds_cache) + self.assertIsNone(pymongocrypt.synchronous.credentials._azure_creds_cache) class KeyVaultCallback(MockCallback): def __init__(self, kms_reply=None): - super(KeyVaultCallback, self).__init__(kms_reply=kms_reply) + super().__init__(kms_reply=kms_reply) self.data_key = None def fetch_keys(self, filter): @@ -620,7 +1160,41 @@ def fetch_keys(self, filter): def insert_data_key(self, data_key): self.data_key = data_key - return bson.decode(data_key, OPTS)['_id'] + return bson.decode(data_key, OPTS)["_id"] + + +def adjust_range_counter(encrypted_val, expected): + """Workaround for the internal range payload counter in libmongocrypt.""" + if encrypted_val != expected: + _payload1 = expected["v"]["$and"][0]["age"]["$gte"] + _payload2 = expected["v"]["$and"][1]["age"]["$lte"] + _decoded1 = bson.decode(_payload1[1:]) + _decoded2 = bson.decode(_payload2[1:]) + for _ in range(10): + _decoded1["payloadId"] += 1 + expected["v"]["$and"][0]["age"]["$gte"] = Binary( + _payload1[0:1] + bson.encode(_decoded1), 6 + ) + _decoded2["payloadId"] += 1 + expected["v"]["$and"][1]["age"]["$lte"] = Binary( + _payload2[0:1] + bson.encode(_decoded2), 6 + ) + if encrypted_val == expected: + break + return expected + + +class AsyncKeyVaultCallback(MockAsyncCallback): + def __init__(self, kms_reply=None): + super().__init__(kms_reply=kms_reply) + self.data_key = None + + async def fetch_keys(self, filter): + return self.data_key + + async def insert_data_key(self, data_key): + self.data_key = data_key + return bson.decode(data_key, OPTS)["_id"] class TestExplicitEncryption(unittest.TestCase): @@ -628,43 +1202,54 @@ class TestExplicitEncryption(unittest.TestCase): @staticmethod def mongo_crypt_opts(): - return MongoCryptOptions({ - 'aws': {'accessKeyId': 'example', 'secretAccessKey': 'example'}, - 'local': {'key': b'\x00'*96}}) + return MongoCryptOptions( + { + "aws": {"accessKeyId": "example", "secretAccessKey": "example"}, + "local": {"key": b"\x00" * 96}, + } + ) def _test_encrypt_decrypt(self, key_id=None, key_alt_name=None): - encrypter = ExplicitEncrypter(MockCallback( - key_docs=[bson_data('key-document.json')], - kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) + encrypter = ExplicitEncrypter( + MockCallback( + key_docs=[bson_data("key-document.json")], + kms_reply=http_data("kms-reply.txt"), + ), + self.mongo_crypt_opts(), + ) self.addCleanup(encrypter.close) - val = {'v': 'hello'} + val = {"v": "hello"} encoded_val = bson.encode(val) algo = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" encrypted = encrypter.encrypt( - encoded_val, algo, key_id=key_id, key_alt_name=key_alt_name) - self.assertEqual(bson.decode(encrypted, OPTS), - json_data('encrypted-value.json')) - self.assertEqual(encrypted, bson_data('encrypted-value.json')) + encoded_val, algo, key_id=key_id, key_alt_name=key_alt_name + ) + self.assertEqual( + bson.decode(encrypted, OPTS), json_data("encrypted-value.json") + ) + self.assertEqual(encrypted, bson_data("encrypted-value.json")) decrypted = encrypter.decrypt(encrypted) self.assertEqual(bson.decode(decrypted, OPTS), val) self.assertEqual(encoded_val, decrypted) def test_encrypt_decrypt(self): - key_id = json_data('key-document.json')['_id'] + key_id = json_data("key-document.json")["_id"] self._test_encrypt_decrypt(key_id=key_id) def test_encrypt_decrypt_key_alt_name(self): - key_alt_name = json_data('key-document.json')['keyAltNames'][0] + key_alt_name = json_data("key-document.json")["keyAltNames"][0] self._test_encrypt_decrypt(key_alt_name=key_alt_name) def test_encrypt_errors(self): - key_id = json_data('key-document.json')['_id'] - encrypter = ExplicitEncrypter(MockCallback(key_docs=[]), self.mongo_crypt_opts()) + key_id = json_data("key-document.json")["_id"] + encrypter = ExplicitEncrypter( + MockCallback(key_docs=[]), self.mongo_crypt_opts() + ) self.addCleanup(encrypter.close) - val = {'v': 'value123'} + val = {"v": "value123"} encoded_val = bson.encode(val) # Invalid algorithm. with self.assertRaisesRegex(MongoCryptError, "algorithm"): @@ -674,122 +1259,189 @@ def test_encrypt_errors(self): encrypter.encrypt(encoded_val, "Indexed", key_id, query_type=42) # Invalid query_type string. with self.assertRaisesRegex(MongoCryptError, "query_type"): - encrypter.encrypt(encoded_val, "Indexed", key_id, query_type='invalid query type string') + encrypter.encrypt( + encoded_val, "Indexed", key_id, query_type="invalid query type string" + ) # Invalid contention_factor type. with self.assertRaisesRegex(TypeError, "contention_factor"): - encrypter.encrypt(encoded_val, "Indexed", key_id, contention_factor='not an int') + encrypter.encrypt( + encoded_val, "Indexed", key_id, contention_factor="not an int" + ) with self.assertRaisesRegex(MongoCryptError, "contention"): encrypter.encrypt(encoded_val, "Indexed", key_id, contention_factor=-1) # Invalid: Unindexed + query_type is an error. with self.assertRaisesRegex(MongoCryptError, "query"): - encrypter.encrypt(encoded_val, "Unindexed", key_id, query_type='equality') + encrypter.encrypt(encoded_val, "Unindexed", key_id, query_type="equality") # Invalid: Unindexed + contention_factor is an error. with self.assertRaisesRegex(MongoCryptError, "contention"): encrypter.encrypt(encoded_val, "Unindexed", key_id, contention_factor=1) def test_encrypt_indexed(self): - key_path = 'keys/ABCDEFAB123498761234123456789012-local-document.json' - key_id = json_data(key_path)['_id'] - encrypter = ExplicitEncrypter(MockCallback( - key_docs=[bson_data(key_path)], - kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) + key_path = "keys/ABCDEFAB123498761234123456789012-local-document.json" + key_id = json_data(key_path)["_id"] + encrypter = ExplicitEncrypter( + MockCallback( + key_docs=[bson_data(key_path)], kms_reply=http_data("kms-reply.txt") + ), + self.mongo_crypt_opts(), + ) self.addCleanup(encrypter.close) - val = {'v': 'value123'} + val = {"v": "value123"} encoded_val = bson.encode(val) for kwargs in [ - dict(algorithm='Indexed', contention_factor=0), - dict(algorithm='Indexed', query_type='equality', contention_factor=0), - dict(algorithm='Indexed', contention_factor=100), - dict(algorithm='Unindexed'), + dict(algorithm="Indexed", contention_factor=0), + dict(algorithm="Indexed", query_type="equality", contention_factor=0), + dict(algorithm="Indexed", contention_factor=100), + dict(algorithm="Unindexed"), ]: - kwargs['key_id'] = key_id + kwargs["key_id"] = key_id encrypted = encrypter.encrypt(encoded_val, **kwargs) - encrypted_val = bson.decode(encrypted, OPTS)['v'] + encrypted_val = bson.decode(encrypted, OPTS)["v"] self.assertIsInstance(encrypted_val, Binary) self.assertEqual(encrypted_val.subtype, 6) # Queryable Encryption find payloads cannot be round-tripped. - if 'query_type' not in kwargs: + if "query_type" not in kwargs: decrypted = encrypter.decrypt(encrypted) self.assertEqual(bson.decode(decrypted, OPTS), val) self.assertEqual(encoded_val, decrypted) def test_data_key_creation(self): - mock_key_vault = KeyVaultCallback( - kms_reply=http_data('kms-encrypt-reply.txt')) - encrypter = ExplicitEncrypter(mock_key_vault, self.mongo_crypt_opts()) + mock_key_vault = KeyVaultCallback(kms_reply=http_data("kms-encrypt-reply.txt")) + opts = MongoCryptOptions( + { + "aws": {"accessKeyId": "example", "secretAccessKey": "example"}, + "aws:named": {"accessKeyId": "example", "secretAccessKey": "example"}, + "local": {"key": b"\x00" * 96}, + "local:named": {"key": b"\x01" * 96}, + } + ) + encrypter = ExplicitEncrypter(mock_key_vault, opts) self.addCleanup(encrypter.close) valid_args = [ - ('local', None, ['first', 'second']), - ('aws', {'region': 'region', 'key': 'cmk'}, ['third', 'forth']), + ("local", None, ["first", "second"]), + ("local:named", None, ["local:named"]), + ("aws", {"region": "region", "key": "cmk"}, ["third", "forth"]), + ("aws:named", {"region": "region", "key": "cmk"}, ["aws:named"]), # Unicode region and key - ('aws', {'region': u'region-unicode', 'key': u'cmk-unicode'}, []), + ("aws", {"region": "region-unicode", "key": "cmk-unicode"}, []), # Endpoint - ('aws', {'region': 'region', 'key': 'cmk', - 'endpoint': 'kms.us-east-1.amazonaws.com:443'}, []), + ( + "aws", + { + "region": "region", + "key": "cmk", + "endpoint": "kms.us-east-1.amazonaws.com:443", + }, + [], + ), ] for kms_provider, master_key, key_alt_names in valid_args: key_id = encrypter.create_data_key( - kms_provider, master_key=master_key, - key_alt_names=key_alt_names) + kms_provider, master_key=master_key, key_alt_names=key_alt_names + ) self.assertIsInstance(key_id, Binary) self.assertEqual(key_id.subtype, 4) data_key = bson.decode(mock_key_vault.data_key, OPTS) # CDRIVER-3277 The order of key_alt_names is not maintained. for name in key_alt_names: - self.assertIn(name, data_key['keyAltNames']) + self.assertIn(name, data_key["keyAltNames"]) # Assert that the custom endpoint is passed to libmongocrypt. - master_key = { - "region": "region", - "key": "key", - "endpoint": "example.com" - } - key_material = base64.b64decode('xPTAjBRG5JiPm+d3fj6XLi2q5DMXUS/f1f+SMAlhhwkhDRL0kr8r9GDLIGTAGlvC+HVjSIgdL+RKwZCvpXSyxTICWSXTUYsWYPyu3IoHbuBZdmw2faM3WhcRIgbMReU5') + master_key = {"region": "region", "key": "key", "endpoint": "example.com"} + key_material = base64.b64decode( + "xPTAjBRG5JiPm+d3fj6XLi2q5DMXUS/f1f+SMAlhhwkhDRL0kr8r9GDLIGTAGlvC+HVjSIgdL+RKwZCvpXSyxTICWSXTUYsWYPyu3IoHbuBZdmw2faM3WhcRIgbMReU5" + ) if not PY3: key_material = Binary(key_material) - encrypter.create_data_key("aws", master_key=master_key, key_material=key_material) + encrypter.create_data_key( + "aws", master_key=master_key, key_material=key_material + ) self.assertEqual("example.com:443", mock_key_vault.kms_endpoint) def test_data_key_creation_bad_key_material(self): - mock_key_vault = KeyVaultCallback( - kms_reply=http_data('kms-encrypt-reply.txt')) + mock_key_vault = KeyVaultCallback(kms_reply=http_data("kms-encrypt-reply.txt")) encrypter = ExplicitEncrypter(mock_key_vault, self.mongo_crypt_opts()) self.addCleanup(encrypter.close) - key_material = Binary(b'0' * 97) - with self.assertRaisesRegex(MongoCryptError, "keyMaterial should have length 96, but has length 97"): + key_material = Binary(b"0" * 97) + with self.assertRaisesRegex( + MongoCryptError, "keyMaterial should have length 96, but has length 97" + ): encrypter.create_data_key("local", key_material=key_material) def test_rewrap_many_data_key(self): - key_path = 'keys/ABCDEFAB123498761234123456789012-local-document.json' - key_path2 = 'keys/12345678123498761234123456789012-local-document.json' - encrypter = ExplicitEncrypter(MockCallback( - key_docs=[bson_data(key_path), bson_data(key_path2)]), self.mongo_crypt_opts()) + key_path = "keys/ABCDEFAB123498761234123456789012-local-document.json" + key_path2 = "keys/12345678123498761234123456789012-local-document.json" + encrypter = ExplicitEncrypter( + MockCallback(key_docs=[bson_data(key_path), bson_data(key_path2)]), + self.mongo_crypt_opts(), + ) self.addCleanup(encrypter.close) result = encrypter.rewrap_many_data_key({}) raw_doc = RawBSONDocument(result) - assert len(raw_doc['v']) == 2 + assert len(raw_doc["v"]) == 2 def test_range_query_int32(self): - key_path = 'keys/ABCDEFAB123498761234123456789012-local-document.json' - key_id = json_data(key_path)['_id'] - encrypter = ExplicitEncrypter(MockCallback( - key_docs=[bson_data(key_path)], - kms_reply=http_data('kms-reply.txt')), self.mongo_crypt_opts()) + key_path = "keys/ABCDEFAB123498761234123456789012-local-document.json" + key_id = json_data(key_path)["_id"] + encrypter = ExplicitEncrypter( + MockCallback( + key_docs=[bson_data(key_path)], kms_reply=http_data("kms-reply.txt") + ), + self.mongo_crypt_opts(), + ) self.addCleanup(encrypter.close) range_opts = bson_data("fle2-find-range-explicit-v2/int32/rangeopts.json") value = bson_data("fle2-find-range-explicit-v2/int32/value-to-encrypt.json") expected = json_data("fle2-find-range-explicit-v2/int32/encrypted-payload.json") encrypted = encrypter.encrypt( - value, "rangePreview", key_id=key_id, query_type="rangePreview", - contention_factor=4, range_opts=range_opts, is_expression=True) + value, + "range", + key_id=key_id, + query_type="range", + contention_factor=4, + range_opts=range_opts, + is_expression=True, + ) encrypted_val = bson.decode(encrypted, OPTS) - self.assertEqual(encrypted_val, expected) + self.assertEqual(encrypted_val, adjust_range_counter(encrypted_val, expected)) + + def test_rangePreview_query_int32(self): + # Expect error attempting to use 'rangePreview' + with self.assertRaisesRegex( + MongoCryptError, + "Algorithm 'rangePreview' is deprecated, please use 'range'", + ): + key_path = "keys/ABCDEFAB123498761234123456789012-local-document.json" + key_id = json_data(key_path)["_id"] + encrypter = ExplicitEncrypter( + MockCallback( + key_docs=[bson_data(key_path)], kms_reply=http_data("kms-reply.txt") + ), + self.mongo_crypt_opts(), + ) + self.addCleanup(encrypter.close) + + range_opts = bson_data( + "fle2-find-rangePreview-explicit/int32/rangeopts.json" + ) + value = bson_data( + "fle2-find-rangePreview-explicit/int32/value-to-encrypt.json" + ) + encrypter.encrypt( + value, + "rangePreview", + key_id=key_id, + query_type="rangePreview", + contention_factor=4, + range_opts=range_opts, + is_expression=True, + ) def read(filename, **kwargs): @@ -799,13 +1451,9 @@ def read(filename, **kwargs): OPTS = CodecOptions(uuid_representation=UuidRepresentation.UNSPECIFIED) -# Use SON to preserve the order of fields while parsing json. -if sys.version_info[:2] < (3, 6): - document_class = SON -else: - document_class = dict -JSON_OPTS = JSONOptions(document_class=document_class, - uuid_representation=UuidRepresentation.UNSPECIFIED) +JSON_OPTS = JSONOptions( + document_class=dict, uuid_representation=UuidRepresentation.UNSPECIFIED +) def json_data(filename): @@ -817,8 +1465,8 @@ def bson_data(filename): def http_data(filename): - data = read(filename, mode='rb') - return data.replace(b'\n', b'\r\n') + data = read(filename, mode="rb") + return data.replace(b"\n", b"\r\n") if __name__ == "__main__": diff --git a/ext/libmongocrypt/libmongocrypt/bindings/python/update-sbom.sh b/ext/libmongocrypt/libmongocrypt/bindings/python/update-sbom.sh new file mode 100755 index 0000000..e0c9031 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/bindings/python/update-sbom.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -eux + +LIBMONGOCRYPT_VERSION=$(cat ./libmongocrypt-version.txt) +if [ $(command -v podman) ]; then + DOCKER=podman +else + DOCKER=docker +fi + +echo "pkg:github/mongodb/libmongocrypt@$LIBMONGOCRYPT_VERSION" > purls.txt +$DOCKER run --platform="linux/amd64" -it --rm -v $(pwd):$(pwd) artifactory.corp.mongodb.com/release-tools-container-registry-public-local/silkbomb:1.0 update --purls=$(pwd)/purls.txt -o $(pwd)/sbom.json +rm purls.txt diff --git a/ext/libmongocrypt/libmongocrypt/cmake/FetchMongoC.cmake b/ext/libmongocrypt/libmongocrypt/cmake/FetchMongoC.cmake index 394cdba..2e25c10 100644 --- a/ext/libmongocrypt/libmongocrypt/cmake/FetchMongoC.cmake +++ b/ext/libmongocrypt/libmongocrypt/cmake/FetchMongoC.cmake @@ -1,12 +1,30 @@ include (FetchContent) # Set the tag that we will fetch. -set (MONGOC_FETCH_TAG_FOR_LIBBSON "1.17.7" CACHE STRING "The Git tag of mongo-c-driver that will be fetched to obtain libbson") +# When updating the version of libbson, also update the version in etc/purls.txt +set (MONGOC_FETCH_TAG_FOR_LIBBSON "1.27.1" CACHE STRING "The Git tag of mongo-c-driver that will be fetched to obtain libbson") + +# Add an option to disable patching if a patch command is unavailable. +option (LIBBSON_PATCH_ENABLED "Whether to apply patches to the libbson library" ON) +set (patch_disabled OFF) +if (NOT LIBBSON_PATCH_ENABLED) + set (patch_disabled ON) +endif () + +include (Patch) +make_patch_command (patch_command + STRIP_COMPONENTS 1 + DIRECTORY "" + DISABLED "${patch_disabled}" + PATCHES + ${PROJECT_SOURCE_DIR}/etc/libbson-remove-GCC-diagnostic-pragma.patch + ) # Fetch the source archive for the requested tag from GitHub FetchContent_Declare ( embedded_mcd URL "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/${MONGOC_FETCH_TAG_FOR_LIBBSON}.tar.gz" + PATCH_COMMAND ${patch_command} --verbose ) # Populate it: FetchContent_GetProperties (embedded_mcd) diff --git a/ext/libmongocrypt/libmongocrypt/cmake/ImportBSON.cmake b/ext/libmongocrypt/libmongocrypt/cmake/ImportBSON.cmake index b337501..b170c69 100644 --- a/ext/libmongocrypt/libmongocrypt/cmake/ImportBSON.cmake +++ b/ext/libmongocrypt/libmongocrypt/cmake/ImportBSON.cmake @@ -132,6 +132,8 @@ function (_import_bson) set (ENABLE_MONGODB_AWS_AUTH OFF CACHE BOOL "Disable kms-message content in mongoc for libmongocrypt" FORCE) # Disable install() for the libbson static library. We'll do it ourselves set (ENABLE_STATIC BUILD_ONLY) + # Disable zlib, which isn't necessary for libmongocrypt and isn't necessarily available. + set (ENABLE_ZLIB OFF CACHE BOOL "Toggle zlib for the mongoc subproject (not required by libmongocrypt)") # Disable libzstd, which isn't necessary for libmongocrypt and isn't necessarily available. set (ENABLE_ZSTD OFF CACHE BOOL "Toggle libzstd for the mongoc subproject (not required by libmongocrypt)") # Disable snappy, which isn't necessary for libmongocrypt and isn't necessarily available. @@ -142,6 +144,21 @@ function (_import_bson) set (ENABLE_EXTRA_ALIGNMENT ${_extra_alignment_default} CACHE BOOL "Toggle extra alignment of bson_t") # We don't want the subproject to find libmongocrypt set (ENABLE_CLIENT_SIDE_ENCRYPTION OFF CACHE BOOL "Disable client-side encryption for the libmongoc subproject") + # Clear `BUILD_VERSION` so C driver does not use a `BUILD_VERSION` meant for libmongocrypt. + # Both libmongocrypt and C driver support setting a `BUILD_VERSION` to override the version. + if (DEFINED CACHE{BUILD_VERSION}) + set (saved_cached_build_version "${BUILD_VERSION}") + unset (BUILD_VERSION CACHE) # Undefine cache variable. + endif () + if (DEFINED BUILD_VERSION) + set (saved_build_version "${BUILD_VERSION}") + unset (BUILD_VERSION) # Undefine normal variable. + endif () + # Disable building tests in C driver: + set (ENABLE_TESTS OFF) + set (BUILD_TESTING OFF) + # Disable counters in C driver. Counters are not supported on all platforms. + set (ENABLE_SHM_COUNTERS OFF) # Add the subdirectory as a project. EXCLUDE_FROM_ALL to inhibit building and installing of components unless requested # SYSTEM (on applicable CMake versions) to prevent warnings (particularly from -Wconversion/-Wsign-conversion) from the C driver code if (CMAKE_VERSION VERSION_GREATER 3.25) @@ -149,6 +166,12 @@ function (_import_bson) else () add_subdirectory ("${MONGOCRYPT_MONGOC_DIR}" _mongo-c-driver EXCLUDE_FROM_ALL) endif () + if (DEFINED saved_cached_build_version) + set (BUILD_VERSION "${saved_cached_build_version}" CACHE STRING "Library version") + endif () + if (DEFINED saved_build_version) + set (BUILD_VERSION "${saved_build_version}") + endif () if (TARGET mongoc_static) # Workaround: Embedded mongoc_static does not set its INCLUDE_DIRECTORIES for user targets target_include_directories (mongoc_static diff --git a/ext/libmongocrypt/libmongocrypt/cmake/IntelDFP.cmake b/ext/libmongocrypt/libmongocrypt/cmake/IntelDFP.cmake index e190e89..74d0eaa 100644 --- a/ext/libmongocrypt/libmongocrypt/cmake/IntelDFP.cmake +++ b/ext/libmongocrypt/libmongocrypt/cmake/IntelDFP.cmake @@ -1,8 +1,7 @@ include (FetchContent) -find_program (GIT_EXECUTABLE git) -find_program (PATCH_EXECUTABLE patch) +# When updating the version of IntelDFP, also update the version in etc/purls.txt set (_default_url "${PROJECT_SOURCE_DIR}/third-party/IntelRDFPMathLib20U2.tar.xz") set (INTEL_DFP_LIBRARY_URL "${_default_url}" @@ -18,16 +17,23 @@ if (NOT INTEL_DFP_LIBRARY_URL_SHA256 STREQUAL "no-verify") set (_hash_arg URL_HASH "${INTEL_DFP_LIBRARY_URL_HASH}") endif () -# Make the PATCH_COMMAND a no-op if it was disabled -set (patch_command) +set (patch_disabled OFF) if (NOT INTEL_DFP_LIBRARY_PATCH_ENABLED) - set (patch_command "${CMAKE_COMMAND}" -E true) -elseif (GIT_EXECUTABLE) - set (patch_command "${GIT_EXECUTABLE}" --work-tree= apply) -else () - set (patch_command "${PATCH_EXECUTABLE}" --dir=) + set (patch_disabled ON) endif () +include (Patch) +make_patch_command (patch_command + STRIP_COMPONENTS 4 + DIRECTORY "" + DISABLED "${patch_disabled}" + PATCHES + "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-s390x.patch" + "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-MONGOCRYPT-571.patch" + "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-libmongocrypt-pr-625.patch" + "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-alpine-arm-fix.patch" + ) + # NOTE: The applying of the patch expects the correct input directly from the # expanded archive. If the patch needs to be reapplied, you may see errors # about trying to update the intel_dfp component. If you are seeing such @@ -37,13 +43,7 @@ FetchContent_Declare ( intel_dfp URL "${_default_url}" ${_hash_arg} - PATCH_COMMAND - ${patch_command} - -p 4 # Strip four path components - "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-s390x.patch" - "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-MONGOCRYPT-571.patch" - "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-libmongocrypt-pr-625.patch" - --verbose + PATCH_COMMAND ${patch_command} --verbose ) FetchContent_GetProperties (intel_dfp) @@ -52,247 +52,39 @@ if (NOT intel_dfp_POPULATED) FetchContent_Populate (intel_dfp) endif () -# This list of sources matches the ones used within MongoDB server. The -# "" prefix is replaced below. +# This list of sources was generated by copying the MongoDB server and removing any unnecessary. +# Carefully add sources if more functionality is needed. Bundled sources are checked by static analysis, and may result in a larger binary. +# The "" prefix is replaced below. # Refer: https://github.com/mongodb/mongo/blob/e9be40f47a77af1931773ad671d4927c0fe6969a/src/third_party/IntelRDFPMathLib20U1/SConscript set (_dfp_sources "/float128/dpml_exception.c" - "/float128/dpml_four_over_pi.c" - "/float128/dpml_ux_bessel.c" "/float128/dpml_ux_bid.c" - "/float128/dpml_ux_cbrt.c" - "/float128/dpml_ux_erf.c" - "/float128/dpml_ux_exp.c" - "/float128/dpml_ux_int.c" - "/float128/dpml_ux_inv_hyper.c" - "/float128/dpml_ux_inv_trig.c" - "/float128/dpml_ux_lgamma.c" "/float128/dpml_ux_log.c" - "/float128/dpml_ux_mod.c" "/float128/dpml_ux_ops.c" "/float128/dpml_ux_ops_64.c" - "/float128/dpml_ux_pow.c" - "/float128/dpml_ux_powi.c" - "/float128/dpml_ux_sqrt.c" - "/float128/dpml_ux_trig.c" - "/float128/sqrt_tab_t.c" "/src/bid128.c" "/src/bid128_2_str_tables.c" - "/src/bid128_acos.c" - "/src/bid128_acosh.c" "/src/bid128_add.c" - "/src/bid128_asin.c" - "/src/bid128_asinh.c" - "/src/bid128_atan.c" - "/src/bid128_atan2.c" - "/src/bid128_atanh.c" - "/src/bid128_cbrt.c" "/src/bid128_compare.c" - "/src/bid128_cos.c" - "/src/bid128_cosh.c" "/src/bid128_div.c" - "/src/bid128_erf.c" - "/src/bid128_erfc.c" - "/src/bid128_exp.c" - "/src/bid128_exp10.c" - "/src/bid128_exp2.c" - "/src/bid128_expm1.c" - "/src/bid128_fdimd.c" "/src/bid128_fma.c" "/src/bid128_fmod.c" - "/src/bid128_frexp.c" - "/src/bid128_hypot.c" - "/src/bid128_ldexp.c" - "/src/bid128_lgamma.c" - "/src/bid128_llrintd.c" - "/src/bid128_log.c" "/src/bid128_log10.c" - "/src/bid128_log1p.c" "/src/bid128_log2.c" - "/src/bid128_logb.c" - "/src/bid128_logbd.c" - "/src/bid128_lrintd.c" - "/src/bid128_lround.c" - "/src/bid128_minmax.c" "/src/bid128_modf.c" "/src/bid128_mul.c" - "/src/bid128_nearbyintd.c" - "/src/bid128_next.c" - "/src/bid128_nexttowardd.c" "/src/bid128_noncomp.c" - "/src/bid128_pow.c" - "/src/bid128_quantexpd.c" - "/src/bid128_quantize.c" - "/src/bid128_rem.c" "/src/bid128_round_integral.c" "/src/bid128_scalb.c" "/src/bid128_scalbl.c" - "/src/bid128_sin.c" - "/src/bid128_sinh.c" - "/src/bid128_sqrt.c" "/src/bid128_string.c" - "/src/bid128_tan.c" - "/src/bid128_tanh.c" - "/src/bid128_tgamma.c" - "/src/bid128_to_int16.c" - "/src/bid128_to_int32.c" "/src/bid128_to_int64.c" - "/src/bid128_to_int8.c" - "/src/bid128_to_uint16.c" - "/src/bid128_to_uint32.c" - "/src/bid128_to_uint64.c" - "/src/bid128_to_uint8.c" - "/src/bid32_acos.c" - "/src/bid32_acosh.c" - "/src/bid32_add.c" - "/src/bid32_asin.c" - "/src/bid32_asinh.c" - "/src/bid32_atan.c" - "/src/bid32_atan2.c" - "/src/bid32_atanh.c" - "/src/bid32_cbrt.c" - "/src/bid32_compare.c" - "/src/bid32_cos.c" - "/src/bid32_cosh.c" - "/src/bid32_div.c" - "/src/bid32_erf.c" - "/src/bid32_erfc.c" - "/src/bid32_exp.c" - "/src/bid32_exp10.c" - "/src/bid32_exp2.c" - "/src/bid32_expm1.c" - "/src/bid32_fdimd.c" - "/src/bid32_fma.c" - "/src/bid32_fmod.c" - "/src/bid32_frexp.c" - "/src/bid32_hypot.c" - "/src/bid32_ldexp.c" - "/src/bid32_lgamma.c" - "/src/bid32_llrintd.c" - "/src/bid32_log.c" - "/src/bid32_log10.c" - "/src/bid32_log1p.c" - "/src/bid32_log2.c" - "/src/bid32_logb.c" - "/src/bid32_logbd.c" - "/src/bid32_lrintd.c" - "/src/bid32_lround.c" - "/src/bid32_minmax.c" - "/src/bid32_modf.c" - "/src/bid32_mul.c" - "/src/bid32_nearbyintd.c" - "/src/bid32_next.c" - "/src/bid32_nexttowardd.c" - "/src/bid32_noncomp.c" - "/src/bid32_pow.c" - "/src/bid32_quantexpd.c" - "/src/bid32_quantize.c" - "/src/bid32_rem.c" - "/src/bid32_round_integral.c" - "/src/bid32_scalb.c" - "/src/bid32_scalbl.c" - "/src/bid32_sin.c" - "/src/bid32_sinh.c" - "/src/bid32_sqrt.c" - "/src/bid32_string.c" - "/src/bid32_sub.c" - "/src/bid32_tan.c" - "/src/bid32_tanh.c" - "/src/bid32_tgamma.c" - "/src/bid32_to_bid128.c" - "/src/bid32_to_bid64.c" - "/src/bid32_to_int16.c" - "/src/bid32_to_int32.c" - "/src/bid32_to_int64.c" - "/src/bid32_to_int8.c" - "/src/bid32_to_uint16.c" - "/src/bid32_to_uint32.c" - "/src/bid32_to_uint64.c" - "/src/bid32_to_uint8.c" - "/src/bid64_acos.c" - "/src/bid64_acosh.c" - "/src/bid64_add.c" - "/src/bid64_asin.c" - "/src/bid64_asinh.c" - "/src/bid64_atan.c" - "/src/bid64_atan2.c" - "/src/bid64_atanh.c" - "/src/bid64_cbrt.c" - "/src/bid64_compare.c" - "/src/bid64_cos.c" - "/src/bid64_cosh.c" - "/src/bid64_div.c" - "/src/bid64_erf.c" - "/src/bid64_erfc.c" - "/src/bid64_exp.c" - "/src/bid64_exp10.c" - "/src/bid64_exp2.c" - "/src/bid64_expm1.c" - "/src/bid64_fdimd.c" - "/src/bid64_fma.c" - "/src/bid64_fmod.c" - "/src/bid64_frexp.c" - "/src/bid64_hypot.c" - "/src/bid64_ldexp.c" - "/src/bid64_lgamma.c" - "/src/bid64_llrintd.c" - "/src/bid64_log.c" - "/src/bid64_log10.c" - "/src/bid64_log1p.c" - "/src/bid64_log2.c" - "/src/bid64_logb.c" - "/src/bid64_logbd.c" - "/src/bid64_lrintd.c" - "/src/bid64_lround.c" - "/src/bid64_minmax.c" - "/src/bid64_modf.c" - "/src/bid64_mul.c" - "/src/bid64_nearbyintd.c" - "/src/bid64_next.c" - "/src/bid64_nexttowardd.c" - "/src/bid64_noncomp.c" - "/src/bid64_pow.c" - "/src/bid64_quantexpd.c" - "/src/bid64_quantize.c" - "/src/bid64_rem.c" - "/src/bid64_round_integral.c" - "/src/bid64_scalb.c" - "/src/bid64_scalbl.c" - "/src/bid64_sin.c" - "/src/bid64_sinh.c" - "/src/bid64_sqrt.c" - "/src/bid64_string.c" - "/src/bid64_tan.c" - "/src/bid64_tanh.c" - "/src/bid64_tgamma.c" "/src/bid64_to_bid128.c" - "/src/bid64_to_int16.c" - "/src/bid64_to_int32.c" - "/src/bid64_to_int64.c" - "/src/bid64_to_int8.c" - "/src/bid64_to_uint16.c" - "/src/bid64_to_uint32.c" - "/src/bid64_to_uint64.c" - "/src/bid64_to_uint8.c" "/src/bid_binarydecimal.c" "/src/bid_convert_data.c" "/src/bid_decimal_data.c" - "/src/bid_decimal_globals.c" - "/src/bid_dpd.c" - "/src/bid_feclearexcept.c" - "/src/bid_fegetexceptflag.c" - "/src/bid_feraiseexcept.c" - "/src/bid_fesetexceptflag.c" - "/src/bid_fetestexcept.c" "/src/bid_flag_operations.c" - "/src/bid_from_int.c" "/src/bid_round.c" - "/src/strtod128.c" - "/src/strtod32.c" - "/src/strtod64.c" - "/src/wcstod128.c" - "/src/wcstod32.c" - "/src/wcstod64.c" ) # Put in the actual library path: string (REPLACE "" "${intel_dfp_SOURCE_DIR}/LIBRARY" _dfp_sources "${_dfp_sources}") diff --git a/ext/libmongocrypt/libmongocrypt/cmake/Patch.cmake b/ext/libmongocrypt/libmongocrypt/cmake/Patch.cmake new file mode 100644 index 0000000..295b8d4 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/cmake/Patch.cmake @@ -0,0 +1,54 @@ +find_program(GIT_EXECUTABLE git) +find_program(PATCH_EXECUTABLE patch) + +#[[ + Form a new Patch-applying command for the given inputs + + make_patch_command( + + [DISABLED ] + [DIRECTORY ] + [STRIP_COMPONENTS ] + PATCHES [ ...] + ) +]] +function(make_patch_command out) + cmake_parse_arguments(PARSE_ARGV 1 patch "" "DIRECTORY;STRIP_COMPONENTS;DISABLED" "PATCHES") + if(patch_DISABLED) + # Use a placeholder "no-op" patch command. + set(cmd "${CMAKE_COMMAND}" "-E" "true") + elseif(GIT_EXECUTABLE) + # git ... + set(cmd ${GIT_EXECUTABLE}) + + if(patch_DIRECTORY) + # git --work-tree=... + list(APPEND cmd --work-tree=${patch_DIRECTORY}) + endif() + # git ... apply ... + list(APPEND cmd apply) + # git ... apply -pN ... + if(patch_STRIP_COMPONENTS) + list(APPEND cmd -p${patch_STRIP_COMPONENTS}) + endif() + # Ignore whitespace errors to fix patch errors on Windows: The patch file may be converted to \r\n by git, but libbson fetched with \n. + list(APPEND cmd "--ignore-whitespace") + # git accepts patch filepaths as positional arguments + list(APPEND cmd ${patch_PATCHES}) + else() + # patch ... + set(cmd ${PATCH_EXECUTABLE}) + if(patch_DIRECTORY) + # patch --dir=... + list(APPEND cmd --dir=${patch_DIRECTORY}) + endif() + # patch ... -pN ... + if(patch_STRIP_COMPONENTS) + list(APPEND cmd -p${patch_STRIP_COMPONENTS}) + endif() + # Prepend "--input=" to each patch filepath and add them to the argv + list(TRANSFORM patch_PATCHES PREPEND "--input=") + list(APPEND cmd ${patch_PATCHES}) + endif() + set("${out}" "${cmd}" PARENT_SCOPE) +endfunction() diff --git a/ext/libmongocrypt/libmongocrypt/debian/build_snapshot.sh b/ext/libmongocrypt/libmongocrypt/debian/build_snapshot.sh deleted file mode 100644 index 49816ba..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/build_snapshot.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh - -# -# build_snapshot.sh -# - -# -# Copyright 2020 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. -# - - -for arg in "$@"; do - if [ "$arg" = "-h" ]; then - echo "Usage: ./debian/build_snapshot.sh" - echo "" - echo " This script is used to build a .deb package directly from a snapshot of the" - echo " current repository." - echo "" - echo " This script must be called from the base directory of the repository, and" - echo " requires utilites from these packages: dpkg-dev, git-buildpackage" - echo "" - exit - fi -done - -package="libmongocrypt" - -if [ ! -x /usr/bin/dpkg-parsechangelog ]; then - echo "Missing the dpkg-parsechangelog utility from the dpkg-dev package" - exit 1 -fi - -if [ ! -f debian/changelog ]; then - echo "This script must be called from the base directory of the package" - exit 1 -fi - -if [ ! -d .git ]; then - echo "This script only works from within a repository" - exit 1 -fi - -if [ ! -x /usr/bin/gbp ]; then - echo "Missing git-buildpackage" - exit 1 -fi - -changelog_package=$(dpkg-parsechangelog | sed -n 's/^Source: //p') -if [ "${package}" != "${changelog_package}" ]; then - echo "This script is configured to create snapshots for ${package} but you are trying to create a snapshot for ${changelog_package}" - exit 1 -fi - -bare_upstream_version=$(sed -E 's/([^-]+).*/\1/' VERSION_CURRENT) -echo "Found bare upstream version: ${bare_upstream_version}" -snapshot_version="${bare_upstream_version}-0+$(date +%Y%m%d)+git$(git rev-parse --short HEAD)" -echo "Upstream snapshot version: ${snapshot_version}" - - -if [ "$(dpkg-parsechangelog | sed -E -n 's/^Version: +(.*)/\1/p')" != "${snapshot_version}" ]; then - echo "Making Debian changelog entry" - dch --force-bad-version --release-heuristic log -v "${snapshot_version}" -D UNRELEASED "Built from Git snapshot." -fi - -echo "Calling git-buildpackage ..." -gbp buildpackage --git-no-pbuilder --git-export=WC --git-verbose - diff --git a/ext/libmongocrypt/libmongocrypt/debian/changelog b/ext/libmongocrypt/libmongocrypt/debian/changelog deleted file mode 100644 index 495de76..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/changelog +++ /dev/null @@ -1,105 +0,0 @@ -libmongocrypt (1.7.2-1) unstable; urgency=medium - - [ Kyle Kloberdanz ] - * Drop remove-builtin.patch, integrated upstream - * Disable Decimal128 on platforms without IntelDFP - - [ Roberto C. Sanchez ] - * New upstream release. - * Ensure that embedded code copies don't get included in .orig.tar.gz - - -- Roberto C. Sanchez Mon, 13 Feb 2023 11:10:37 -0500 - -libmongocrypt (1.7.1-2) unstable; urgency=medium - - * Remove builtin which causes 32-bit ARM builds to fail - - -- Kyle Kloberdanz Fri, 03 Feb 2023 16:24:00 -0600 - -libmongocrypt (1.7.1-1) unstable; urgency=medium - - [ Roberto C. Sanchez ] - * Add libintelrdfpmath-dev to Build-Depends rather than using embedded - sources. - - [ Kyle Kloberdanz ] - * New upstream release. - * Add myself to uploaders. - * Update to Standards-Version 4.6.2 (no changes) - - -- Kyle Kloberdanz Fri, 03 Feb 2023 13:25:46 -0600 - -libmongocrypt (1.6.2-1) unstable; urgency=medium - - * New upstream release. - - -- Roberto C. Sanchez Tue, 06 Dec 2022 23:50:00 -0500 - -libmongocrypt (1.6.0-1) unstable; urgency=medium - - * New upstream release. - - -- Roberto C. Sanchez Wed, 07 Sep 2022 20:54:40 -0400 - -libmongocrypt (1.5.2-1) unstable; urgency=medium - - * New upstream release. - - -- Roberto C. Sanchez Sat, 30 Jul 2022 11:07:08 -0400 - -libmongocrypt (1.5.0-1) unstable; urgency=medium - - * New upstream release. - * Update to Standards-Version 4.6.1 (no changes) - - -- Roberto C. Sanchez Tue, 28 Jun 2022 16:05:33 -0400 - -libmongocrypt (1.4.0-1) unstable; urgency=medium - - * New upstream release. - - -- Roberto C. Sanchez Mon, 18 Apr 2022 18:46:10 -0400 - -libmongocrypt (1.3.1-1) unstable; urgency=medium - - * New upstream release. - - -- Roberto C. Sanchez Wed, 02 Mar 2022 14:05:42 -0500 - -libmongocrypt (1.3.0-1) unstable; urgency=medium - - * New upstream release. - - -- Roberto C. Sanchez Thu, 04 Nov 2021 17:38:47 -0400 - -libmongocrypt (1.2.2-1) unstable; urgency=medium - - * New upstream release. - * Update to Standards-Version 4.6.0 (no changes) - - -- Roberto C. Sanchez Tue, 07 Sep 2021 21:43:35 -0400 - -libmongocrypt (1.2.1-1) unstable; urgency=medium - - * New upstream release. - - -- Roberto C. Sanchez Tue, 13 Jul 2021 19:21:05 -0400 - -libmongocrypt (1.2.0-1) unstable; urgency=medium - - * New upstream release. - - -- Roberto C. Sanchez Wed, 03 Mar 2021 12:15:27 -0500 - -libmongocrypt (1.1.0-1) unstable; urgency=medium - - * New upstream release. - * Update to Standards-Version 4.5.1 (no changes) - - -- Roberto C. Sanchez Tue, 12 Jan 2021 14:17:05 -0500 - -libmongocrypt (1.0.4-1) unstable; urgency=medium - - * Initial release (Closes: #968995). - - -- Roberto C. Sanchez Tue, 25 Aug 2020 11:07:58 -0400 diff --git a/ext/libmongocrypt/libmongocrypt/debian/compat b/ext/libmongocrypt/libmongocrypt/debian/compat deleted file mode 100644 index f599e28..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/compat +++ /dev/null @@ -1 +0,0 @@ -10 diff --git a/ext/libmongocrypt/libmongocrypt/debian/control b/ext/libmongocrypt/libmongocrypt/debian/control deleted file mode 100644 index 89f5dfd..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/control +++ /dev/null @@ -1,41 +0,0 @@ -Source: libmongocrypt -Priority: optional -Maintainer: Mongo C Driver Team -Uploaders: Kevin Albertson , - Roberto C. Sanchez , - Kyle Kloberdanz -Build-Depends: debhelper (>= 10), - cmake, - libssl-dev, - pkg-config, - libintelrdfpmath-dev (>= 2.0u2-6) [!mips64el !mipsel], - libbson-dev -Standards-Version: 4.6.2 -Section: libs -Homepage: https://github.com/mongodb/libmongocrypt - -Package: libmongocrypt-dev -Section: libdevel -Architecture: any -Multi-Arch: same -Depends: libbson-dev, - libmongocrypt0 (= ${binary:Version}), - libintelrdfpmath-dev (>= 2.0u2-6) [!mips64el !mipsel], - ${misc:Depends} -Description: client-side field level encryption library - dev files - libmongocrypt facilitates the client-side encryption and decryption, - at the field level, of data stored in MongoDB. - . - This package contains the libmongocrypt and libkms_message development - headers and libraries. - -Package: libmongocrypt0 -Architecture: any -Multi-Arch: same -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: client-side field level encryption library - runtime files - libmongocrypt facilitates the client-side encryption and decryption, - at the field level, of data stored in MongoDB. - . - This package contains the libmongocrypt and libkms_message runtime - libraries. diff --git a/ext/libmongocrypt/libmongocrypt/debian/copyright b/ext/libmongocrypt/libmongocrypt/debian/copyright deleted file mode 100644 index 256c0d2..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/copyright +++ /dev/null @@ -1,129 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: libmongocrypt -Source: https://github.com/mongodb/libmongocrypt - -Files: * -Copyright: 2008-present MongoDB, Inc. -License: Apache-2.0 - -Files: debian/* -Copyright: 2020 MongoDB, Inc. -License: Apache-2.0 - -Files: kms-message/aws-sig-v4-test-suite/* -Copyright: 2017 Amazon.com, Inc. or its affiliates. -License: Apache-2.0 - -Files: kms-message/src/sort.c -Copyright: 1992, 1993 The Regents of the University of California. -License: BSD-3-clause - -Files: kms-message/src/kms_b64.c -Copyright: 1996, 1998 Internet Software Consortium - 1995 International Business Machines, Inc. -License: ISC or Other-IBM - -Files: kms-message/test/windows/dirent.h -Copyright: 2006-2012 Toni Ronkko -License: MIT - -License: Apache-2.0 - 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 - . - https://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. - . - On Debian systems, the complete text of the Apache version 2.0 license - can be found in "/usr/share/common-licenses/Apache-2.0". - -License: BSD-3-clause - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - . - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -License: ISC - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - . - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -License: Other-IBM - Portions Copyright (c) 1995 by International Business Machines, Inc. - . - International Business Machines, Inc. (hereinafter called IBM) grants - permission under its copyrights to use, copy, modify, and distribute this - Software with or without fee, provided that the above copyright notice and - all paragraphs of this notice appear in all copies, and that the name of IBM - not be used in connection with the marketing of any product incorporating - the Software or modifications thereof, without specific, written prior - permission. - . - To the extent it has a right to do so, IBM grants an immunity from suit - under its patents, if any, for the use, sale or manufacture of products to - the extent that such products are used for performing Domain Name System - dynamic updates in TCP/IP networks by means of the Software. No immunity is - granted for any product per se or for any other function of any product. - . - THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, - INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, - DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING - OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN - IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. - -License: MIT - The MIT License (MIT) - . - Copyright (c) 1998-2019 Toni Ronkko - . - 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. diff --git a/ext/libmongocrypt/libmongocrypt/debian/gbp.conf b/ext/libmongocrypt/libmongocrypt/debian/gbp.conf deleted file mode 100644 index 0c6db9c..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/gbp.conf +++ /dev/null @@ -1,23 +0,0 @@ -[DEFAULT] -pristine-tar = False -no-create-orig = True -pbuilder = True - -prebuild = bash -c " - # Show execution trace - set -x && - # Use debian/changelog (not VERSION_CURRENT) to get upstream version to build - upstream_version=$(dpkg-parsechangelog | sed -E -n 's/^Version: +(.*)-.*/\1/p') && - # Determine list of embedded sources to exclude from Debian source package - third_party_filter_files=\"$([ -d third-party ] && find third-party/ -mindepth 1 -maxdepth 1 -printf "libmongocrypt-\${upstream_version}/%p ")\" && - third_party_rm_files=\"$([ -d third-party ] && find third-party/ -mindepth 1 -maxdepth 1 -printf '%p ')\" && - # Create upstream tarball from reference, exclude items that do not belong - pushd $GBP_GIT_DIR/.. && - git archive --format=tar --prefix=libmongocrypt-\${upstream_version}/ HEAD | tar -f - --delete libmongocrypt-\${upstream_version}/debian \$third_party_filter_files | gzip > $GBP_BUILD_DIR/../libmongocrypt_\${upstream_version}.orig.tar.gz && - popd && - rm -rf \$third_party_rm_files" - -upstream-tree = BRANCH -upstream-branch = master -upstream-tag = %(version)s -debian-branch = master diff --git a/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt-dev.dirs b/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt-dev.dirs deleted file mode 100644 index 4418816..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt-dev.dirs +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib -usr/include diff --git a/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt-dev.install b/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt-dev.install deleted file mode 100644 index ef2e1d7..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt-dev.install +++ /dev/null @@ -1,5 +0,0 @@ -usr/include/* -usr/lib/*/lib*.a -usr/lib/*/lib*.so -usr/lib/*/cmake/* -usr/lib/*/pkgconfig/* diff --git a/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt0.dirs b/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt0.dirs deleted file mode 100644 index 6845771..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt0.dirs +++ /dev/null @@ -1 +0,0 @@ -usr/lib diff --git a/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt0.install b/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt0.install deleted file mode 100644 index 3ddde58..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/libmongocrypt0.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/lib*.so.* diff --git a/ext/libmongocrypt/libmongocrypt/debian/rules b/ext/libmongocrypt/libmongocrypt/debian/rules deleted file mode 100755 index 6991663..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/rules +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/make -f -# See debhelper(7) (uncomment to enable) -# output every command that modifies files on the build system. -#export DH_VERBOSE = 1 - -# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/* -DPKG_EXPORT_BUILDFLAGS = 1 -include /usr/share/dpkg/default.mk -include /usr/share/dpkg/pkg-info.mk - -# see FEATURE AREAS in dpkg-buildflags(1) -export DEB_BUILD_MAINT_OPTIONS = hardening=+all - -# see ENVIRONMENT in dpkg-buildflags(1) -# package maintainers to append CFLAGS -#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic -export DEB_CFLAGS_MAINT_APPEND = -fPIC -# package maintainers to append LDFLAGS -#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed - -ifneq (,$(filter $(DEB_HOST_ARCH),mipsel mips64el)) - DFP_CONFIG_OPTION=-DMONGOCRYPT_ENABLE_DECIMAL128=OFF -else - DFP_CONFIG_OPTION=-DMONGOCRYPT_DFP_DIR=USE-SYSTEM -endif - -%: - dh $@ - -override_dh_auto_configure: - dh_auto_configure -B$(CURDIR)/cmake-build -- \ - -DBUILD_VERSION=$(DEB_VERSION_UPSTREAM) \ - -DUSE_SHARED_LIBBSON=ON \ - -DMONGOCRYPT_MONGOC_DIR=USE-SYSTEM \ - -DENABLE_ONLINE_TESTS=OFF \ - $(DFP_CONFIG_OPTION) \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -override_dh_auto_build: - dh_auto_build -B$(CURDIR)/cmake-build -- all - -override_dh_auto_install: - dh_auto_install -B$(CURDIR)/cmake-build - -override_dh_missing: - dh_missing --fail-missing diff --git a/ext/libmongocrypt/libmongocrypt/debian/source/format b/ext/libmongocrypt/libmongocrypt/debian/source/format deleted file mode 100644 index 163aaf8..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/ext/libmongocrypt/libmongocrypt/debian/source/lintian-overrides b/ext/libmongocrypt/libmongocrypt/debian/source/lintian-overrides deleted file mode 100644 index 84a92cf..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/source/lintian-overrides +++ /dev/null @@ -1,3 +0,0 @@ -# This file is a source file. The presence of base64-encoded cryptographic -# keys results in very long lines. -libmongocrypt source: source-is-missing [bindings/node/test/cryptoCallbacks.test.js] diff --git a/ext/libmongocrypt/libmongocrypt/debian/source/options b/ext/libmongocrypt/libmongocrypt/debian/source/options deleted file mode 100644 index 9845b22..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/source/options +++ /dev/null @@ -1 +0,0 @@ -extend-diff-ignore = (\.idea|cmake-build-debug) diff --git a/ext/libmongocrypt/libmongocrypt/debian/watch b/ext/libmongocrypt/libmongocrypt/debian/watch deleted file mode 100644 index af449ad..0000000 --- a/ext/libmongocrypt/libmongocrypt/debian/watch +++ /dev/null @@ -1,3 +0,0 @@ -version=4 -opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libmongocrypt-$1.tar.gz%" \ -https://github.com/mongodb/libmongocrypt/tags (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate diff --git a/ext/libmongocrypt/libmongocrypt/doc/img/cli-icon.png b/ext/libmongocrypt/libmongocrypt/doc/img/cli-icon.png new file mode 100644 index 0000000..e244824 Binary files /dev/null and b/ext/libmongocrypt/libmongocrypt/doc/img/cli-icon.png differ diff --git a/ext/libmongocrypt/libmongocrypt/doc/img/reference-targets.png b/ext/libmongocrypt/libmongocrypt/doc/img/reference-targets.png new file mode 100644 index 0000000..de13f70 Binary files /dev/null and b/ext/libmongocrypt/libmongocrypt/doc/img/reference-targets.png differ diff --git a/ext/libmongocrypt/libmongocrypt/doc/releasing.md b/ext/libmongocrypt/libmongocrypt/doc/releasing.md new file mode 100644 index 0000000..c2a2a43 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/doc/releasing.md @@ -0,0 +1,153 @@ +# Releasing libmongocrypt + +These steps describe releasing the libmongocrypt C library (not the language bindings). + +## Version number scheme ## +Version numbers of libmongocrypt must follow the format 1.[0-9].[0-9] for releases and 1.[0-9].[0-9]-(alpha|beta|rc)[0-9] for pre-releases. This ensures that Linux distribution packages built from each commit are published to the correct location. + +## Steps to release ## + +### Check for Vulnerabilities + +Snyk and Silk are used to satisfy vulnerability scanning requirements of [DRIVERS-714](https://jira.mongodb.org/browse/DRIVERS-714). Prior to releasing, ensure necessary reported vulnerabilities meet requirements described in: [MongoDB Software Security Development Lifecycle Policy](https://docs.google.com/document/d/1u0m4Kj2Ny30zU74KoEFCN4L6D_FbEYCaJ3CQdCYXTMc/edit?tab=t.0#bookmark=id.l09k96qt24jm). + +#### Check Snyk + +Go to [Snyk](https://app.snyk.io/) and select the `dev-prod` organization. If access is needed, see [Snyk Onboarding](https://docs.google.com/document/d/1A38HvDvVFOwLtJQfQwIGcy5amAIpDwHUkNInwezLwXY/edit#heading=h.9ayipd2nt7xg). Check the CLI target named `mongodb/libmongocrypt`. The CLI targets may be identified by this icon: ![CLI icon](img/cli-icon.png). There are reference targets for each tracked branch: + +![Reference Targets](img/reference-targets.png) + +Copy the organization ID from [Snyk settings](https://app.snyk.io/org/dev-prod/manage/settings). + +##### Update Snyk + +Update the Snyk reference target tracking the to-be-released branch. For a patch release (e.g. x.y.z), check-out the `rx.y` branch and update the `rx.y` reference target. For a minor release (e.g. x.y.0), check out the `master` branch update the `master` reference target. + +Run `cmake` to ensure generated source files are present: +```bash +cmake -S. -Bcmake-build -D BUILD_TESTING=OFF +cmake --build cmake-build --target mongocrypt +``` + +Print dependencies found by Snyk and verify libbson is found: +```bash +snyk test --unmanaged --print-dep-paths +``` + +Copy the organization ID from [Snyk settings](https://app.snyk.io/org/dev-prod/manage/settings). Create the new Snyk reference target to track the newly created release branch: +```bash +snyk auth +snyk monitor \ +--org=$ORGANIZATION_ID \ +--target-reference="" \ +--unmanaged \ +--remote-repo-url=https://github.com/mongodb/libmongocrypt.git +``` + +```bash +snyk auth +snyk monitor \ +--org=$ORGANIZATION_ID \ +--target-reference= \ +--unmanaged \ +--remote-repo-url=https://github.com/mongodb/libmongocrypt.git +``` + +Check the updated reference targets in Snyk for detected vulnerabilities. + +#### Check Silk + +Get credentials for Silk from the `drivers/libmongocrypt` vault in [AWS Secrets Manager](https://wiki.corp.mongodb.com/display/DRIVERS/Using+AWS+Secrets+Manager+to+Store+Testing+Secrets). + +Download the Augmented SBOM using: +```bash +./.evergreen/earthly.sh \ + --secret silk_client_id=${silk_client_id} \ + --secret silk_client_secret=${silk_client_secret} \ + +sbom-download \ + --out cyclonedx.augmented.sbom.json \ + --branch +``` + +Check the contents of the "vulnerabilities" field (if present) in the Augmented SBOM. + +### Release + +Do the following when releasing: +- If this is a feature release (e.g. `x.y.0` or `x.0.0`), follow these steps: [Creating SSDLC static analysis reports](https://docs.google.com/document/d/1rkFL8ymbkc0k8Apky9w5pTPbvKRm68wj17mPJt2_0yo/edit). +- Check out the release branch. For a release `x.y.z`, the release branch is `rx.y`. If this is a new minor release (`x.y.0`), create the release branch. +- Update CHANGELOG.md with the version being released. +- Ensure `etc/purls.txt` is up-to-date. +- Update `etc/third_party_vulnerabilities.md` with any updates to new or known vulnerabilities for third party dependencies that must be reported. +- If this is a new minor release (e.g. `x.y.0`): + - Update the Linux distribution package installation instructions in the below sections to refer to the new version `x.y`. + - Update the [libmongocrypt-release](https://spruce.mongodb.com/project/libmongocrypt-release/settings/general) Evergreen project (requires auth) to set `Branch Name` to `rx.y`. +- Commit the changes on the `rx.y` branch with a message like "Update CHANGELOG.md for x.y.z". +- Tag the commit with `git tag -a `. + - Push both the branch ref and tag ref in the same command: `git push origin master 1.8.0-alpha0` or `git push origin r1.8 1.8.4` + - Pushing the branch ref and the tag ref in the same command eliminates the possibility of a race condition in Evergreen (for building resources based on the presence of a release tag) + - Note that in the future (e.g., if we move to a PR-based workflow for releases, or if we simply want to take better advantage of advanced Evergreen features), it is possible to use Evergreen's "Trigger Versions With Git Tags" feature by updating both `config.yml` and the project's settings in Evergreen +- Ensure the version on Evergreen with the tagged commit is scheduled. The following tasks must pass to complete the release: + - `upload-all` + - `windows-upload-release` + - All `publish-packages` tasks. + - If the `publish-packages` tasks fail with an error like `[curator] 2024/01/02 13:56:17 [p=emergency]: problem submitting repobuilder job: 404 (Not Found)`, this suggests the published path does not yet exist. Barque (the Linux package publishing service) has protection to avoid unintentional publishes. File a DEVPROD ticket ([example](https://jira.mongodb.org/browse/DEVPROD-4053)) and assign to the team called Release Infrastructure to request the path be created. Then re-run the failing `publish-packages` task. Ask in the slack channel `#devprod-release-tools` for further help with `Barque` or `curator`. +- Create the release from the GitHub releases page from the new tag. + - Attach the tarball and signature file from the Files tab of the `windows-upload-release` task. [Example](https://github.com/mongodb/libmongocrypt/releases/tag/1.10.0). + - Attach the Augmented SBOM file. Download the Augmented SBOM using: + ```bash + ./.evergreen/earthly.sh \ + --secret silk_client_id=${silk_client_id} \ + --secret silk_client_secret=${silk_client_secret} \ + +sbom-download \ + --out cyclonedx.augmented.sbom.json \ + --branch + ``` + For a new minor release, use `master` for `--branch`. For a patch release, use the release branch (e.g. `rx.y`). + Secrets can be obtained from [AWS Secrets Manager](https://wiki.corp.mongodb.com/display/DRIVERS/Using+AWS+Secrets+Manager+to+Store+Testing+Secrets) under `drivers/libmongocrypt`. + - Attach `etc/third_party_vulnerabilities.md` to the release. + - Attach `ssdlc_compliance_report.md` to the release. + +- If this is a new minor release (e.g. `x.y.0`): + - File a DOCSP ticket to update the installation instructions on [Install libmongocrypt](https://www.mongodb.com/docs/manual/core/csfle/reference/libmongocrypt/). ([Example](https://jira.mongodb.org/browse/DOCSP-36863)) + - Create a new Silk asset group. Use the newly created release branch (e.g. `rx.y`) as the `--branch` argument: + ```bash + ./.evergreen/earthly.sh \ + --secret silk_client_id=${silk_client_id} \ + --secret silk_client_secret=${silk_client_secret} \ + +silk-create-asset-group \ + --branch + ``` + - Create a new Snyk reference target. The following instructions use the example branch `rx.y`: + + Run `cmake` to ensure generated source files are present: + ```bash + cmake -S. -Bcmake-build -D BUILD_TESTING=OFF + cmake --build cmake-build --target mongocrypt + ``` + + Print dependencies found by Snyk and verify libbson is found: + ```bash + snyk test --unmanaged --print-dep-paths + ``` + + Copy the organization ID from [Snyk settings](https://app.snyk.io/org/dev-prod/manage/settings). Create the new Snyk reference target to track the newly created release branch: + ```bash + snyk auth + snyk monitor \ + --org=$ORGANIZATION_ID \ + --target-reference=rx.y \ + --unmanaged \ + --remote-repo-url=https://github.com/mongodb/libmongocrypt.git + ``` + Snyk reference targets for older release branches may be removed if no further releases are expected on the branch. +- Make a PR to apply the "Update CHANGELOG.md for x.y.z" commit to the `master` branch. +- Update the release on the [Jira releases page](https://jira.mongodb.org/projects/MONGOCRYPT/versions). +- Record the release on [C/C++ Release Info](https://docs.google.com/spreadsheets/d/1yHfGmDnbA5-Qt8FX4tKWC5xk9AhzYZx1SKF4AD36ecY/edit?usp=sharing). This is done to meet SSDLC reporting requirements. +- Add a link to the Evergreen waterfall for the tagged commit to [libmongocrypt Security Testing Summary](https://docs.google.com/document/d/1dc7uvBzu3okAIsA8LSW5sVQGkYIvwpBVdg5v4wb4c4s/edit#heading=h.5t79jwe4p0ss). + +## Homebrew steps ## +Submit a PR to update the Homebrew package https://github.com/mongodb/homebrew-brew/blob/master/Formula/libmongocrypt.rb. ([Example](https://github.com/mongodb/homebrew-brew/pull/208)). If not on macOS, request a team member to do this step. + +## Debian steps ## +Refer to the [Debian](https://github.com/mongodb/mongo-c-driver/blob/master/docs/dev/debian.rst) steps. If you are not a Debian maintainer on the team, request a team member to do this step. diff --git a/ext/libmongocrypt/libmongocrypt/etc/calc_release_version.py b/ext/libmongocrypt/libmongocrypt/etc/calc_release_version.py index 9e2b685..26bf164 100644 --- a/ext/libmongocrypt/libmongocrypt/etc/calc_release_version.py +++ b/ext/libmongocrypt/libmongocrypt/etc/calc_release_version.py @@ -22,11 +22,35 @@ current Git commit. """ +# XXX NOTE XXX NOTE XXX NOTE XXX +# After modifying this script it is advisable to execute the self-test. +# +# This is done by starting in the directory containing this script and then +# executing a separate self-test script, like this: +# +# $ bash ./calc_release_version_selftest.sh +# +# The self-test script will emit diagnostic output. If tracing of the execution +# of each command is desired, then add the -x option to the bash invocation. +# XXX NOTE XXX NOTE XXX NOTE XXX + import datetime import re import subprocess import sys -from distutils.version import LooseVersion +try: + # Prefer newer `packaging` over deprecated packages. + from packaging.version import Version as Version + from packaging.version import parse as parse_version +except ImportError: + # Fallback to deprecated pkg_resources. + try: + from pkg_resources.extern.packaging.version import Version + from pkg_resources import parse_version + except ImportError: + # Fallback to deprecated distutils. + from distutils.version import LooseVersion as Version + from distutils.version import LooseVersion as parse_version DEBUG = len(sys.argv) > 1 and '-d' in sys.argv if DEBUG: @@ -70,7 +94,8 @@ def check_head_tag(): """ found_tag = False - version_loose = LooseVersion('0.0.0') + version_str = '0.0.0' + version_parsed = parse_version(version_str) # have git tell us if any tags that look like release tags point at HEAD; # based on our policy, a commit should never have more than one release tag @@ -83,17 +108,19 @@ def check_head_tag(): release_tag_match = RELEASE_TAG_RE.match(tag) if release_tag_match: - new_version_loose = LooseVersion(release_tag_match.group('ver')) - if new_version_loose > version_loose: + new_version_str = release_tag_match.group('ver') + new_version_parsed = parse_version(new_version_str) + if new_version_parsed > version_parsed: if DEBUG: - print('HEAD release tag: ' + release_tag_match.group('ver')) - version_loose = new_version_loose + print('HEAD release tag: ' + new_version_str) + version_str = new_version_str + version_parsed = new_version_parsed found_tag = True if found_tag: if DEBUG: - print('Calculated version: ' + str(version_loose)) - return str(version_loose) + print('Calculated version: ' + version_str) + return version_str return None @@ -106,7 +133,8 @@ def get_next_minor(prerelease_marker): - Append a pre-release marker. (e.g. 1.22.0 becomes 1.22.0-20220201+gitf6e6a7025d) """ - version_loose = LooseVersion('0.0.0') + version_str = '0.0.0' + version_parsed = parse_version(version_str) version_new = {} # Use refs (not branches) to get local branches plus remote branches @@ -119,17 +147,19 @@ def get_next_minor(prerelease_marker): version_new['minor'] = int(release_branch_match.group('vermin')) + 1 version_new['patch'] = 0 version_new['prerelease'] = prerelease_marker - new_version_loose = LooseVersion(str(version_new['major']) + '.' + - str(version_new['minor']) + '.' + - str(version_new['patch']) + '-' + - version_new['prerelease']) - if new_version_loose > version_loose: - version_loose = new_version_loose + new_version_str = str(version_new['major']) + '.' + \ + str(version_new['minor']) + '.' + \ + str(version_new['patch']) + '-' + \ + version_new['prerelease'] + new_version_parsed = parse_version(new_version_str) + if new_version_parsed > version_parsed: + version_str = new_version_str + version_parsed = new_version_parsed if DEBUG: - print('Found new best version "' + str(version_loose) \ + print('Found new best version "' + version_str \ + '" based on branch "' \ + release_branch_match.group('brname') + '"') - return str(version_loose) + return version_str def get_branch_tags(active_branch_name): """ @@ -167,7 +197,7 @@ def get_branch_tags(active_branch_name): def process_and_sort_tags(tags): """ Given a string (as returned from get_branch_tags), return a sorted list of - zero or more tags (sorted based on the LooseVersion comparison) which meet + zero or more tags (sorted based on the Version comparison) which meet the following criteria: - a final release tag (i.e., 1.x.y without any pre-release suffix) - a pre-release tag which is not superseded by a release tag (i.e., @@ -190,7 +220,7 @@ def process_and_sort_tags(tags): tag_parts = tag.split('-') if len(tag_parts) >= 2 and tag_parts[0] not in processed_and_sorted_tags: processed_and_sorted_tags.append(tag) - processed_and_sorted_tags.sort(key=LooseVersion) + processed_and_sorted_tags.sort(key=Version) return processed_and_sorted_tags @@ -211,7 +241,8 @@ def main(): patch version, and append a new pre-release marker """ - version_loose = LooseVersion('0.0.0') + version_str = '0.0.0' + version_parsed = parse_version(version_str) head_commit_short = check_output(['git', 'rev-parse', '--revs-only', '--short=10', 'HEAD^{commit}']).strip() prerelease_marker = datetime.date.today().strftime('%Y%m%d') \ @@ -246,17 +277,19 @@ def main(): version_new['minor'] = int(release_tag_match.group('vermin')) version_new['patch'] = int(release_tag_match.group('verpatch')) + 1 version_new['prerelease'] = prerelease_marker - new_version_loose = LooseVersion(str(version_new['major']) + '.' + - str(version_new['minor']) + '.' + - str(version_new['patch']) + '-' + - version_new['prerelease']) - if new_version_loose > version_loose: - version_loose = new_version_loose + new_version_str = str(version_new['major']) + '.' + \ + str(version_new['minor']) + '.' + \ + str(version_new['patch']) + '-' + \ + version_new['prerelease'] + new_version_parsed = parse_version(new_version_str) + if new_version_parsed > version_parsed: + version_str = new_version_str + version_parsed = new_version_parsed if DEBUG: - print('Found new best version "' + str(version_loose) \ + print('Found new best version "' + version_str \ + '" from tag "' + release_tag_match.group('ver') + '"') - return str(version_loose) + return version_str RELEASE_VER = main() diff --git a/ext/libmongocrypt/libmongocrypt/etc/calc_release_version_selftest.sh b/ext/libmongocrypt/libmongocrypt/etc/calc_release_version_selftest.sh new file mode 100755 index 0000000..7fd9787 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/etc/calc_release_version_selftest.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# calc_release_version_selftest.sh is used to test output of calc_release_version.py. +# run with: +# cd etc +# ./calc_release_version_selftest.sh + +set -o errexit +set -o pipefail + +function assert_eq () { + a="$1" + b="$2" + if [[ "$a" != "$b" ]]; then + echo "Assertion failed: $a != $b" + # Print caller + caller + exit 1 + fi +} + +SAVED_REF=$(git rev-parse HEAD) + +function cleanup () { + [[ -e calc_release_version_test.py ]] && rm calc_release_version_test.py + git checkout $SAVED_REF --quiet +} + +trap cleanup EXIT + +: ${PYTHON_INTERP:=python} +if [[ -z $(command -v "${PYTHON_INTERP}") ]]; then + echo "Python interpreter '${PYTHON_INTERP}' is not valid." + echo "Set the PYTHON_INTERP environment variable to a valid interpreter." + exit 1 +fi + +# copy calc_release_version.py to a separate file not tracked by git so it does not change on `git checkout` +cp calc_release_version.py calc_release_version_test.py + +echo "Test a tagged commit ... begin" +{ + git checkout 1.8.1 --quiet + got=$("${PYTHON_INTERP}" calc_release_version_test.py) + assert_eq "$got" "1.8.1" + git checkout - --quiet +} +echo "Test a tagged commit ... end" + +DATE=$(date +%Y%m%d) +echo "Test an untagged commit ... begin" +{ + # b7f8a1f1502d28a5ef440e642fddda8da8f873a1 is commit before 1.8.1 + git checkout b7f8a1f1502d28a5ef440e642fddda8da8f873a1 --quiet + got=$("${PYTHON_INTERP}" calc_release_version_test.py) + assert_eq "$got" "1.8.1-$DATE+gitb7f8a1f150" + git checkout - --quiet +} +echo "Test an untagged commit ... end" + +echo "Test next minor version ... begin" +{ + CURRENT_SHORTREF=$(git rev-parse --revs-only --short=10 HEAD) + got=$("${PYTHON_INTERP}" calc_release_version_test.py --next-minor) + # XXX NOTE XXX NOTE XXX + # If you find yourself looking at this line because the assertion below + # failed, then it is probably because a new major/minor release was made. + # Update the expected output to represent the correct next version. + # XXX NOTE XXX NOTE XXX + assert_eq "$got" "1.9.0-$DATE+git$CURRENT_SHORTREF" +} +echo "Test next minor version ... end" + +echo "All tests passed" diff --git a/ext/libmongocrypt/libmongocrypt/etc/cyclonedx.sbom.json b/ext/libmongocrypt/libmongocrypt/etc/cyclonedx.sbom.json new file mode 100644 index 0000000..a12ef9b --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/etc/cyclonedx.sbom.json @@ -0,0 +1,108 @@ +{ + "components": [ + { + "bom-ref": "pkg:github/mongodb/mongo-c-driver@v1.27.1#src/libbson", + "copyright": "Copyright 2009-present MongoDB, Inc.", + "externalReferences": [ + { + "type": "distribution", + "url": "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/v1.27.1.tar.gz" + }, + { + "type": "website", + "url": "https://github.com/mongodb/mongo-c-driver/tree/v1.27.1" + } + ], + "group": "mongodb", + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ], + "name": "mongo-c-driver", + "purl": "pkg:github/mongodb/mongo-c-driver@v1.27.1#src/libbson", + "type": "library", + "version": "v1.27.1" + }, + { + "bom-ref": "pkg:generic/IntelRDFPMathLib@20U2?download_url=https://www.netlib.org/misc/intel/IntelRDFPMathLib20U2.tar.gz", + "copyright": "Copyright (c) 2018, Intel Corp.", + "externalReferences": [ + { + "type": "distribution", + "url": "https://www.netlib.org/misc/intel/IntelRDFPMathLib20U2.tar.gz" + } + ], + "licenses": [ + { + "license": { + "id": "BSD-3-Clause" + } + } + ], + "name": "IntelRDFPMathLib", + "purl": "pkg:generic/IntelRDFPMathLib@20U2?download_url=https://www.netlib.org/misc/intel/IntelRDFPMathLib20U2.tar.gz", + "type": "library", + "version": "20U2" + } + ], + "dependencies": [ + { + "ref": "pkg:generic/IntelRDFPMathLib@20U2?download_url=https://www.netlib.org/misc/intel/IntelRDFPMathLib20U2.tar.gz" + }, + { + "ref": "pkg:github/mongodb/mongo-c-driver@v1.27.1#src/libbson" + } + ], + "metadata": { + "timestamp": "2024-05-10T12:07:55.084050+00:00", + "tools": [ + { + "externalReferences": [ + { + "type": "build-system", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/actions" + }, + { + "type": "distribution", + "url": "https://pypi.org/project/cyclonedx-python-lib/" + }, + { + "type": "documentation", + "url": "https://cyclonedx-python-library.readthedocs.io/" + }, + { + "type": "issue-tracker", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/issues" + }, + { + "type": "license", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE" + }, + { + "type": "release-notes", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md" + }, + { + "type": "vcs", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib" + }, + { + "type": "website", + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" + } + ], + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "6.4.4" + } + ] + }, + "serialNumber": "urn:uuid:879e1b41-08d8-4505-8c89-2285bc3e442c", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.5" +} diff --git a/ext/libmongocrypt/libmongocrypt/etc/format.sh b/ext/libmongocrypt/libmongocrypt/etc/format.sh index 7210cfc..b326b47 100755 --- a/ext/libmongocrypt/libmongocrypt/etc/format.sh +++ b/ext/libmongocrypt/libmongocrypt/etc/format.sh @@ -10,7 +10,7 @@ if ! run_python -c ''; then fi # Check that we have a pipx of the proper version: -run_python -c 'import pkg_resources; pkg_resources.require("pipx>=0.17.0<2.0")' +run_python -c 'import pkg_resources; pkg_resources.require("pipx>=0.17.0,<2.0")' # Give default clang-format an empty string on stdin if there are no inputs files printf '' | run_python -m pipx run "clang-format==${CLANG_FORMAT_VERSION:?}" "$@" diff --git a/ext/libmongocrypt/libmongocrypt/etc/libbson-remove-GCC-diagnostic-pragma.patch b/ext/libmongocrypt/libmongocrypt/etc/libbson-remove-GCC-diagnostic-pragma.patch new file mode 100644 index 0000000..f556b4c --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/etc/libbson-remove-GCC-diagnostic-pragma.patch @@ -0,0 +1,27 @@ +diff --git a/src/common/bson-dsl.h b/src/common/bson-dsl.h +index 58a14e28e..3341e603f 100644 +--- a/src/common/bson-dsl.h ++++ b/src/common/bson-dsl.h +@@ -29,6 +29,13 @@ enum { + BSON_IF_WINDOWS (__declspec (selectany)) \ + BSON_IF_POSIX (__attribute__ ((weak))) + ++#if defined(__GNUC__) && !defined(__clang__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)) ++// Using GCC < 4.6 ++// Do not define `GCC diagnostic` pragma for GCC < 4.6. ++#define _bsonDSL_disableWarnings() ((void) 0) ++#define _bsonDSL_restoreWarnings() ((void) 0) ++#else ++// Not using GCC < 4.6 + #ifdef __GNUC__ + // GCC has a bug handling pragma statements that disable warnings within complex + // nested macro expansions. If we're GCC, just disable -Wshadow outright: +@@ -47,7 +54,7 @@ BSON_IF_GNU_LIKE (_Pragma ("GCC diagnostic ignored \"-Wshadow\"")) + BSON_IF_GNU_LIKE (_Pragma ("GCC diagnostic pop");) \ + } else \ + ((void) 0) +- ++#endif + /** + * @brief Parse the given BSON document. + * diff --git a/ext/libmongocrypt/libmongocrypt/etc/mongo-inteldfp-alpine-arm-fix.patch b/ext/libmongocrypt/libmongocrypt/etc/mongo-inteldfp-alpine-arm-fix.patch new file mode 100644 index 0000000..0a8fc04 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/etc/mongo-inteldfp-alpine-arm-fix.patch @@ -0,0 +1,17 @@ +diff --git a/cmake-build/_deps/intel_dfp-src/LIBRARY/src/bid_functions.h b/cmake-build/_deps/intel_dfp-src/LIBRARY/src/bid_functions.h +index 7042eed..e55f59e 100755 +--- a/cmake-build/_deps/intel_dfp-src/LIBRARY/src/bid_functions.h ++++ b/cmake-build/_deps/intel_dfp-src/LIBRARY/src/bid_functions.h +@@ -41,12 +41,6 @@ + #endif + #include + +-// Fix system header issue on Sun solaris and define required type by ourselves +-#if !defined(_WCHAR_T) && !defined(_WCHAR_T_DEFINED) && !defined(__QNX__) && !defined(__cplusplus) +-typedef int wchar_t; +-#endif +- +- + #ifdef IN_LIBGCC2 + // When we are built as the part of the gcc runtime library, libgcc, + // we will use gcc types defined in bid_gcc_intrinsics.h. diff --git a/ext/libmongocrypt/libmongocrypt/etc/packager.py b/ext/libmongocrypt/libmongocrypt/etc/packager.py index cc4e1c2..df9e305 100755 --- a/ext/libmongocrypt/libmongocrypt/etc/packager.py +++ b/ext/libmongocrypt/libmongocrypt/etc/packager.py @@ -5,13 +5,11 @@ by downloading our tarballs and forming them into Linux packages. It must be run on a Debianoid, since Debian provides tools to make RPMs, but RPM-based systems don't provide debian packaging crud. -This program is also based on the program of the same name in the -MongoDB server repository. This program was adapted from the program of the same name in the MongoDB server repository: -https://github.com/mongodb/mongo/blob/v4.2/buildscripts/packager.py +https://github.com/mongodb/mongo/blob/master/buildscripts/packager.py Notes ----- @@ -33,6 +31,25 @@ apt-get install dpkg-dev rpm debhelper fakeroot ia32-libs createrepo git-core echo "Now put the dist gnupg signing keys in ~root/.gnupg" +Differences from the server version of this script +-------------------------------------------------- + +* The version numbering scheme is a bit different, so the regexes in +this script are modified to match the versioning of libmongocrypt. +Naturally, instances of the package name 'mongodb' have been replaced +with 'libmongocrypt', and since libmonogcrypt does not use the 'org' +and 'enterprise' suffixes, those have been left out as well. + +* The server version of this script has been updated to generate the +changelog based on Git history, while this version of the script +continues to use the boilerplate changelog. + +* Other specific divergences, especially where care should be taken in +order to not clobber when syncing changes from the server version of +the script, are noted with explanatory comments as needed. These +comments are prefixed 'MC:' to make them easily distinguished from +other comments coming from the original source. + """ import argparse @@ -48,10 +65,10 @@ import time # The MongoDB names for the architectures we support. -ARCH_CHOICES = ["x86_64", "arm64", "s390x", "ppc64le"] +ARCH_CHOICES = ["x86_64", "arm64", "aarch64", "s390x", "ppc64le"] # Made up names for the flavors of distribution we package for. -DISTROS = ["suse", "debian", "redhat", "ubuntu", "amazon", "amazon2"] +DISTROS = ["suse", "debian", "redhat", "ubuntu", "amazon", "amazon2", "amazon2023"] class Spec(object): @@ -63,7 +80,7 @@ def __init__(self, ver, gitspec=None, rel=None): self.gitspec = gitspec self.rel = rel - # Commit-triggerd (nightly) version numbers can be in the form: 3.0.7-pre-, or 3.0.7-5-g3b67ac + # Commit-triggerd version numbers can be in the form: 3.0.7-pre-, or 3.0.7-5-g3b67ac # Patch builds version numbers are in the form: 3.5.5-64-g03945fa-patch-58debcdb3ff1223c9d00005b # def is_nightly(self): @@ -79,6 +96,7 @@ def is_rc(self): """Return True if rc.""" return bool(re.search(r"-rc\d+(\+[0-9]{8}git[0-9a-f]+)?$", self.version())) + # MC: libmongocrypt also has beta releases def is_beta(self): """Return True if beta.""" return bool(re.search(r"-beta\d+(\+[0-9]{8}git[0-9a-f]+)?$", self.version())) @@ -106,6 +124,9 @@ def metadata_gitspec(self): return self.gitspec return 'r' + self.version() + # MC: Leave out the version_better_than() and suffix() funtions, which are + # not used by libmongocrypt's packaging workflow + def prelease(self): """Return pre-release verison suffix.""" # NOTE: This is only called for RPM packages, and only after @@ -192,7 +213,6 @@ def archname(self, arch): Power and x86 have different names for apt/yum (ppc64le/ppc64el and x86_64/amd64). """ - # pylint: disable=too-many-return-statements if re.search("^(debian|ubuntu)", self.dname): if arch == "ppc64le": return "ppc64el" @@ -208,14 +228,15 @@ def archname(self, arch): return "ppc64le" elif arch == "s390x": return "s390x" - elif arch == "arm64": - return "aarch64" elif arch.endswith("86"): return "i686" + elif arch == "arm64": + return "arm64" + elif arch == "aarch64": + return "aarch64" return "x86_64" else: raise Exception("BUG: unsupported platform?") - # pylint: enable=too-many-return-statements def repodir(self, arch, build_os, spec): # noqa: D406,D407,D412,D413 """Return the directory where we'll place the package files for (distro, distro_version). @@ -267,6 +288,8 @@ def repo_component(self): Example, "universe" for Ubuntu, "main" for debian. """ + # MC: libmongocrypt uses the 'universe' section for Ubuntu, rather than + # 'multiverse' like the server if self.dname == 'ubuntu': return "universe" elif self.dname == 'debian': @@ -274,13 +297,13 @@ def repo_component(self): else: raise Exception("unsupported distro: %s" % self.dname) - def repo_os_version(self, build_os): # pylint: disable=too-many-branches + def repo_os_version(self, build_os): """Return an OS version suitable for package repo directory naming. Example, 5, 6 or 7 for redhat/centos, "precise," "wheezy," etc. for Ubuntu/Debian, 11 for suse, "2013.03" for amazon. """ - # pylint: disable=too-many-return-statements + if self.dname == 'suse': return re.sub(r'^suse(\d+)$', r'\1', build_os) if self.dname == 'redhat': @@ -289,6 +312,8 @@ def repo_os_version(self, build_os): # pylint: disable=too-many-branches return "2013.03" elif self.dname == 'amazon2': return "2017.12" + elif self.dname == 'amazon2023': + return "2023.0" elif self.dname == 'ubuntu': if build_os == 'ubuntu1204': return "precise" @@ -313,11 +338,12 @@ def repo_os_version(self, build_os): # pylint: disable=too-many-branches return 'buster' elif build_os == 'debian11': return 'bullseye' + elif build_os == 'debian12': + return 'bookworm' else: raise Exception("unsupported build_os: %s" % build_os) else: raise Exception("unsupported distro: %s" % self.dname) - # pylint: enable=too-many-return-statements def make_pkg(self, build_os, arch, spec, srcdir): """Return the package.""" @@ -335,14 +361,26 @@ def build_os(self, arch): "suse11" for suse, etc. """ # Community builds only support amd64 - if arch not in ['x86_64', 'ppc64le', 's390x', 'arm64']: + if arch not in ['x86_64', 'ppc64le', 's390x', 'arm64', 'aarch64']: raise Exception("BUG: unsupported architecture (%s)" % arch) if re.search("(suse)", self.dname): return ["suse11", "suse12", "suse15"] elif re.search("(redhat|fedora|centos)", self.dname): - return ["rhel80", "rhel70", "rhel71", "rhel72", "rhel62", "rhel55", "rhel67"] - elif self.dname in ['amazon', 'amazon2']: + return [ + "rhel91", + "rhel83", + "rhel82", + "rhel81", + "rhel80", + "rhel70", + "rhel71", + "rhel72", + "rhel62", + "rhel55", + "rhel67" + ] + elif self.dname in ['amazon', 'amazon2', 'amazon2023']: return [self.dname] elif self.dname == 'ubuntu': return [ @@ -354,7 +392,7 @@ def build_os(self, arch): "ubuntu2204", ] elif self.dname == 'debian': - return ["debian81", "debian92", "debian10", "debian11"] + return ["debian81", "debian92", "debian10", "debian11", "debian12"] else: raise Exception("BUG: unsupported platform?") @@ -370,6 +408,8 @@ def release_dist(self, build_os): return 'amzn1' elif self.dname == 'amazon2': return 'amzn2' + elif self.dname == 'amazon2023': + return 'amzn2023' return re.sub(r'^rh(el\d).*$', r'\1', build_os) @@ -489,7 +529,7 @@ def setupdir(distro, build_os, arch, spec): # would be dst/x86_64/debian-sysvinit/wheezy/libmongocrypt/ # or dst/x86_64/redhat/rhel55/libmongocrypt/ return "dst/%s/%s/%s/%s-%s/" % (arch, distro.name(), build_os, distro.pkgbase(), - spec.pversion(distro)) + spec.pversion(distro)) def unpack_binaries_into(build_os, arch, spec, where): @@ -504,7 +544,10 @@ def unpack_binaries_into(build_os, arch, spec, where): try: sysassert(["tar", "xvzf", rootdir + "/" + tarfile(build_os, arch, spec)]) release_dir = glob('libmongocrypt-*')[0] - for releasefile in "lib", "lib64", "include": + for releasefile in "lib", "lib64", "include", "LICENSE", "README.md": + # MC: wrap print() and os.rename() in a conditional since as a library + # we have to consider that sometimes artifacts are in lib and other + # times they are in lib64 if os.path.exists("%s/%s" % (release_dir, releasefile)): print("moving file: %s/%s" % (release_dir, releasefile)) os.rename("%s/%s" % (release_dir, releasefile), releasefile) @@ -524,16 +567,23 @@ def make_package(distro, build_os, arch, spec, srcdir): sdir = setupdir(distro, build_os, arch, spec) ensure_dir(sdir) + # Note that the RPM packages get their man pages from the debian + # directory, so the debian directory is needed in all cases (and + # innocuous in the debianoids' sdirs). for pkgdir in ["etc/debian", "etc/rpm"]: print("Copying packaging files from %s to %s" % ("%s/%s" % (srcdir, pkgdir), sdir)) + # FIXME: sh-dash-cee is bad. See if tarfile can do this. sysassert([ "sh", "-c", + # MC: we use --strip-components=1 since the 'debian/' and 'rpm/' + # dirs are under 'etc/' in the libmongocrypt repo "(cd \"%s\" && tar cf - %s ) | (cd \"%s\" && tar --strip-components=1 -xvf -)" % (srcdir, pkgdir, sdir) ]) # Splat the binaries under sdir. The "build" stages of the # packaging infrastructure will move the files to wherever they # need to go. unpack_binaries_into(build_os, arch, spec, sdir) + return distro.make_pkg(build_os, arch, spec, srcdir) @@ -549,6 +599,11 @@ def make_repo(repodir, distro, build_os): def make_deb(distro, build_os, arch, spec, srcdir): """Make the Debian script.""" + # I can't remember the details anymore, but the initscript/upstart + # job files' names must match the package name in some way; and + # see also the --name flag to dh_installinit in the generated + # debian/rules file. + # MC: We leave out all the stuff that the server does related to init scripts sdir = setupdir(distro, build_os, arch, spec) # Rewrite the control and rules files write_debian_changelog(sdir + "debian/changelog", spec, srcdir, distro) @@ -560,6 +615,9 @@ def make_deb(distro, build_os, arch, spec, srcdir): "cp", "-v", srcdir + "etc/debian/rules", sdir + "debian/rules" ]) + # MC: Skip some server-specific things, like variations of the controls and + # rules files, as well as maintainer scripts (i.e., postinst) + # Do the packaging. oldcwd = os.getcwd() try: @@ -621,7 +679,7 @@ def make_deb_repo(repo, distro, build_os): os.chdir(oldpwd) -def move_repos_into_place(src, dst): # pylint: disable=too-many-branches +def move_repos_into_place(src, dst): """Move the repos into place.""" # Find all the stuff in src/*, move it to a freshly-created # directory beside dst, then play some games with symlinks so that @@ -690,6 +748,8 @@ def write_debian_changelog(path, spec, srcdir, distro): """Write the debian changelog.""" oldcwd = os.getcwd() os.chdir(srcdir) + # MC: Rather than using Git to generate the changelog (like the server), we + # just use a simple boilerplate changelog preamble = "libmongocrypt (%s-0) unstable; urgency=medium\n\n" % spec.pversion(distro) preamble += " * Built from Evergreen.\n\n" preamble += " -- Roberto C. Sanchez " @@ -701,72 +761,26 @@ def write_debian_changelog(path, spec, srcdir, distro): ]).decode('utf-8') finally: os.chdir(oldcwd) + # MC: No need to munge the version and rewrite the changelog with open(path, 'w') as fh: fh.write(sb) -def make_rpm(distro, build_os, arch, spec, srcdir): # pylint: disable=too-many-locals +def make_rpm(distro, build_os, arch, spec, srcdir): """Create the RPM specfile.""" sdir = setupdir(distro, build_os, arch, spec) specfile = srcdir + "etc/rpm/libmongocrypt.spec" + # No need to mess with init scripts and such like the server + topdir = ensure_dir('%s/rpmbuild/%s/' % (os.getcwd(), build_os)) for subdir in ["BUILD", "RPMS", "SOURCES", "SPECS", "SRPMS"]: ensure_dir("%s/%s/" % (topdir, subdir)) distro_arch = distro.archname(arch) - # RPM tools take these macro files that define variables in - # RPMland. Unfortunately, there's no way to tell RPM tools to use - # a given file *in addition* to the files that it would already - # load, so we have to figure out what it would normally load, - # augment that list, and tell RPM to use the augmented list. To - # figure out what macrofiles ordinarily get loaded, older RPM - # versions had a parameter called "macrofiles" that could be - # extracted from "rpm --showrc". But newer RPM versions don't - # have this. To tell RPM what macros to use, older versions of - # RPM have a --macros option that doesn't work; on these versions, - # you can put a "macrofiles" parameter into an rpmrc file. But - # that "macrofiles" setting doesn't do anything for newer RPM - # versions, where you have to use the --macros flag instead. And - # all of this is to let us do our work with some guarantee that - # we're not clobbering anything that doesn't belong to us. - # - # On RHEL systems, --rcfile will generally be used and - # --macros will be used in Ubuntu. - # - macrofiles = [ - l for l in backtick(["rpm", "--showrc"]).decode('utf-8').split("\n") - if l.startswith("macrofiles") - ] - flags = [] - macropath = os.getcwd() + "/macros" - - write_rpm_macros_file(macropath, topdir, distro.release_dist(build_os)) - if macrofiles: - macrofiles = macrofiles[0] + ":" + macropath - rcfile = os.getcwd() + "/rpmrc" - write_rpmrc_file(rcfile, macrofiles) - flags = ["--rcfile", rcfile] - else: - # This hard-coded hooey came from some box running RPM - # 4.4.2.3. It may not work over time, but RPM isn't sanely - # configurable. - flags = [ - "--macros", - "/usr/lib/rpm/macros:/usr/lib/rpm/%s-linux/macros:/usr/lib/rpm/suse/macros:/etc/rpm/macros.*:/etc/rpm/macros:/etc/rpm/%s-linux/macros:~/.rpmmacros:%s" - % (distro_arch, distro_arch, macropath) - ] - # Put the specfile and the tar'd up binaries and stuff in - # place. - # - # The version of rpm and rpm tools in RHEL 5.5 can't interpolate the - # %{dynamic_version} macro, so do it manually - with open(specfile, "r") as spec_source: - with open(topdir + "SPECS/" + os.path.basename(specfile), "w") as spec_dest: - for line in spec_source: - line = line.replace('%{dynamic_version}', spec.pversion(distro)) - line = line.replace('%{dynamic_release}', spec.prelease()) - spec_dest.write(line) + + # Places the RPM Spec file where it's expected for the rpmbuild execution later. + shutil.copy(specfile, topdir + "SPECS") oldcwd = os.getcwd() os.chdir(sdir + "/../") @@ -780,10 +794,39 @@ def make_rpm(distro, build_os, arch, spec, srcdir): # pylint: disable=too-many- os.chdir(oldcwd) # Do the build. - flags.extend([ - "-D", "dynamic_version " + spec.pversion(distro), "-D", - "dynamic_release " + spec.prelease(), "-D", "_topdir " + topdir - ]) + # MC: Dump the rpm config. + bt = backtick(["rpm", "--showrc"]).decode('utf-8') + print(bt) + # + # MC: Add some macro definitions to the rpmbuild invocation: + # + # _arch - it seems like this one ought to be defined by RPM, but it appears + # to not be and without it the build fails to find some artifacts + # + # _smp_build_ncpus - it seems that on some platforms xargs is invoked in + # such a way that if _smp_build_ncpus is not set (which it apparently is not + # on every platform) then the xargs invocation fails + # + # debug_package - tells rpmbuild that there is no package to build with + # debugging information/symbols; we don't generate them and since we are + # packaging a library rpmbuild expects to find them + # + flags = [ + "-D", + "_smp_build_ncpus 1", + "-D", + "debug_package %{nil}", + "-D", + "_arch {}".format(arch), + "-D", + "_topdir {}".format(topdir), + "-D", + "dist .{}".format(distro.release_dist(build_os)), + "-D", + "dynamic_version {}".format(spec.pversion(distro)), + "-D", + "dynamic_release {}".format(spec.prelease()), + ] # Versions of RPM after 4.4 ignore our BuildRoot tag so we need to # specify it on the command line args to rpmbuild @@ -814,20 +857,6 @@ def make_rpm_repo(repo): os.chdir(oldpwd) -def write_rpmrc_file(path, string): - """Write the RPM rc file.""" - with open(path, 'w') as fh: - fh.write(string) - - -def write_rpm_macros_file(path, topdir, release_dist): - """Write the RPM macros file.""" - with open(path, 'w') as fh: - fh.write("%%_topdir %s\n" % topdir) - fh.write("%%dist .%s\n" % release_dist) - fh.write("%_use_internal_dependency_generator 0\n") - - def ensure_dir(filename): """Ensure that the dirname directory of filename exists, and return filename.""" dirpart = os.path.dirname(filename) diff --git a/ext/libmongocrypt/libmongocrypt/etc/purls.txt b/ext/libmongocrypt/libmongocrypt/etc/purls.txt new file mode 100644 index 0000000..b6b8558 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/etc/purls.txt @@ -0,0 +1,14 @@ +# These package URLs (purls) point to the versions (tags) of external dependencies +# that are committed to the project. Refer: https://github.com/package-url/purl-spec + +# This file is fed to silkbomb to generate the cyclonedx.sbom.json file. Edit this file +# instead of modifying the SBOM JSON directly. After modifying this file, be sure to +# re-generate the SBOM JSON file with: `./.evergreen/earthly.sh +sbom-generate`. If +# adding a new dependency, ensure the resulting SBOM JSON includes the `licenses` and +# `copyright` property. This information can be manually added. + +# libbson is obtained via `cmake/FetchMongoC.cmake`. +pkg:github/mongodb/mongo-c-driver@v1.27.1?#src/libbson + +# IntelDFP is obtained via `cmake/IntelDFP.cmake` +pkg:generic/IntelRDFPMathLib@20U2?download_url=https://www.netlib.org/misc/intel/IntelRDFPMathLib20U2.tar.gz diff --git a/ext/libmongocrypt/libmongocrypt/etc/repo_config.yaml b/ext/libmongocrypt/libmongocrypt/etc/repo_config.yaml index fcb2a15..19f99fa 100644 --- a/ext/libmongocrypt/libmongocrypt/etc/repo_config.yaml +++ b/ext/libmongocrypt/libmongocrypt/etc/repo_config.yaml @@ -106,6 +106,42 @@ repos: - yum/redhat/8/libmongocrypt - yum/redhat/8Server/libmongocrypt + - name: rhel81 + type: rpm + edition: org + bucket: libmongocrypt + region: us-east-1 + repos: + - yum/redhat/8/libmongocrypt + - yum/redhat/8Server/libmongocrypt + + - name: rhel82 + type: rpm + edition: org + bucket: libmongocrypt + region: us-east-1 + repos: + - yum/redhat/8/libmongocrypt + - yum/redhat/8Server/libmongocrypt + + - name: rhel83 + type: rpm + edition: org + bucket: libmongocrypt + region: us-east-1 + repos: + - yum/redhat/8/libmongocrypt + - yum/redhat/8Server/libmongocrypt + + - name: rhel91 + type: rpm + edition: org + bucket: libmongocrypt + region: us-east-1 + repos: + - yum/redhat/9/libmongocrypt + - yum/redhat/9Server/libmongocrypt + - name: amazon type: rpm edition: org @@ -122,6 +158,14 @@ repos: repos: - yum/amazon/2/libmongocrypt + - name: amazon2023 + type: rpm + edition: org + bucket: libmongocrypt + region: us-east-1 + repos: + - yum/amazon/2023/libmongocrypt + - name: suse12 type: rpm edition: org @@ -187,6 +231,18 @@ repos: repos: - apt/debian/dists/bullseye/libmongocrypt + - name: debian12 + type: deb + code_name: "bookworm" + bucket: libmongocrypt + region: us-east-1 + edition: org + component: main + architectures: + - amd64 + repos: + - apt/debian/dists/bookworm/libmongocrypt + - name: ubuntu1404 type: deb code_name: "trusty" diff --git a/ext/libmongocrypt/libmongocrypt/etc/silk-create-asset-group.sh b/ext/libmongocrypt/libmongocrypt/etc/silk-create-asset-group.sh new file mode 100755 index 0000000..9581662 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/etc/silk-create-asset-group.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +set -o errexit +set -o pipefail +set -o nounset + +# Check for required commands: +if ! command -v jq > /dev/null 2>&1; then + echo "jq not found. Install jq" + exit 1 +fi + +if ! command -v curl > /dev/null 2>&1; then + echo "curl not found. Install curl" + exit 1 +fi + +# Check for required environment variables: +: "${silk_client_id:?}" +: "${silk_client_secret:?}" +: "${branch:?}" + +# Get Silk token: +json_payload=$(cat < + +## Tool used to track third party vulnerabilities + +Silk and Snyk. + +## Third-Party Dependency Information + +See `cyclonedx.augmented.sbom.json` attached to release. + +## Static Analysis Findings + +See [SSDLC Static Analysis Reports](https://drive.google.com/drive/folders/17bjBnQ3mhEXvs6IK1rrTphJr0CUO2qZh?usp=sharing) (internal) for release-specific reports. + +## Security Testing Report + +See [libmongocrypt Security Testing Summary](https://docs.google.com/document/d/1dc7uvBzu3okAIsA8LSW5sVQGkYIvwpBVdg5v4wb4c4s?usp=sharing) (internal). Available as needed from the libmongocrypt team. + +## Security Assessment Report + +Not applicable to libmongocrypt. + +## Signature Information + +Signatures for Windows binaries are attached to this release and may be verified with `gpg`. The public key for `libmongocrypt` is available on https://pgp.mongodb.com/. + +## Known Vulnerabilities + +Any vulnerabilities that may be shown in the links referenced above have been reviewed and accepted by the appropriate approvers. For detailed information, see `third_party_vulnerabilities.md` attached to release. diff --git a/ext/libmongocrypt/libmongocrypt/etc/third_party_vulnerabilities.md b/ext/libmongocrypt/libmongocrypt/etc/third_party_vulnerabilities.md new file mode 100644 index 0000000..ae8c407 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/etc/third_party_vulnerabilities.md @@ -0,0 +1,42 @@ +# 3rd Party Dependency Vulnerabilities + +This document tracks vulnerabilities in 3rd party dependencies that directly affect the standard release product of libmongocrypt. + +> [!IMPORTANT] +> The "standard release product" is defined as the set of files which are _installed_ by a configuration, build, and install of libmongocrypt. This includes static/shared library files, header files, and packaging files for supported build configurations. Vulnerabilities for 3rd party dependencies that are bundled with the standard release product are reported in this document. +> +> Language bindings (in the `bindings` directory), test files, utility scripts, documentation generators, and other miscellaneous files and artifacts are NOT considered part of the standard release product, even if they are included in the release distribution tarball. Vulnerabilities for such 3rd party dependencies are NOT reported in this document. + +## Template + +This section provides a template that may be used for actual vulnerability reports further below. + +### CVE-YYYY-NNNNNN + +- **Date Detected:** YYYY-MM-DD +- **Severity:** Low, Medium, High, or Critical +- **Detector:** Silk or Snyk +- **Description:** A short vulnerability description. +- **Dependency:** Name and version of the 3rd party dependency. +- **Upstream Status:** False Positive, Won't Fix, Fix Pending, or Fix Available. This is the fix status for the 3rd party dependency, not libmongocrypt. "Fix Available" should include the version and/or date when the fix was released, e.g. "Fix Available (1.2.3, 1970-01-01)". +- **Fix Status:** False Positive, Won't Fix, Fix Pending, or Fix Committed. This is the fix status for the libmongocrypt. "False Positive" and "Won't Fix" must include rationale in notes below. +- **For Release:** The libmongocrypt release version for which the "Fix Status" above was last updated. +- **Notes:** Context or rationale for remediation, references to relevant issue trackers, etc. + +## libbson + +### CVE-2023-0437 + +- **Date Detected:** 2024-05-20 +- **Severity:** Medium +- **Detector:** Snyk +- **Description:** Loop with Unreachable Exit Condition ('Infinite Loop') +- **Dependency:** mongodb/mongo-c-driver@1.17.7 +- **Upstream Status:** Fix Available (1.25.0, 2023-11-01). +- **Fix Status:** Fix Committed. +- **For Release:** 1.10.1 +- **Notes:** Fixed in libbson 1.25.0 ([CDRIVER-4747](https://jira.mongodb.org/browse/CDRIVER-4747)). Fixed in libmongocrypt by upgrading libbson to 1.27.1 ([MONGOCRYPT-685](https://jira.mongodb.org/browse/MONGOCRYPT-685)). + +## IntelDFP + +None. diff --git a/ext/libmongocrypt/libmongocrypt/integrating.md b/ext/libmongocrypt/libmongocrypt/integrating.md index 5ef1520..fe9b231 100644 --- a/ext/libmongocrypt/libmongocrypt/integrating.md +++ b/ext/libmongocrypt/libmongocrypt/integrating.md @@ -18,7 +18,7 @@ The binding uses the native language\'s foreign function interface to C. For example, Java can accomplish this with [JNA](https://github.com/java-native-access/jna), CPython with [extensions](https://docs.python.org/3/extending/extending.html), -NodeJS with [add-ons](https://nodejs.org/api/addons.html), etc. +Node.js with [add-ons](https://nodejs.org/api/addons.html), etc. The libmongocrypt library files (.so/.dll) are pre-built on its [Evergreen project](https://evergreen.mongodb.com/waterfall/libmongocrypt). Click @@ -137,6 +137,23 @@ A result from a listCollections cursor. auto encrypt +#### State: `MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB` #### + +**libmongocrypt needs**... + +Results from a listCollections cursor from a specified database. + +**Driver needs to...** + +1. Run listCollections on the encrypted MongoClient with the filter + provided by `mongocrypt_ctx_mongo_op` on the database provided by `mongocrypt_ctx_mongo_db`. +2. Return the first result (if any) with `mongocrypt_ctx_mongo_feed` or proceed to the next step if nothing was returned. +3. Call `mongocrypt_ctx_mongo_done` + +**Applies to...** + +A context initialized with `mongocrypt_ctx_encrypt_init` for automatic encryption. This state is only entered when `mongocrypt_setopt_use_need_mongo_collinfo_with_db_state` is called to opt-in. + #### State: `MONGOCRYPT_CTX_NEED_MONGO_MARKINGS` #### **libmongocrypt needs**... diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/CMakeLists.txt b/ext/libmongocrypt/libmongocrypt/kms-message/CMakeLists.txt index aa9e04d..f6e3324 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/CMakeLists.txt +++ b/ext/libmongocrypt/libmongocrypt/kms-message/CMakeLists.txt @@ -71,6 +71,14 @@ else() "KMS_MESSAGE_ENABLE_CRYPTO_LIBCRYPTO") endif() +include (CheckSymbolExists) +CHECK_SYMBOL_EXISTS (gmtime_r time.h KMS_MESSAGE_HAVE_GMTIME_R) +if (KMS_MESSAGE_HAVE_GMTIME_R) + set (KMS_MESSAGE_DEFINITIONS + ${KMS_MESSAGE_DEFINITIONS} + "KMS_MESSAGE_HAVE_GMTIME_R") +endif () + include (TestBigEndian) TEST_BIG_ENDIAN (KMS_BIG_ENDIAN) if (KMS_BIG_ENDIAN) @@ -114,9 +122,9 @@ if (NOT DISABLE_NATIVE_CRYPTO) else() include (FindOpenSSL) target_link_libraries(kms_message "${OPENSSL_LIBRARIES}") - target_include_directories(kms_message PRIVATE "${OPENSSL_INCLUDE_DIR}") + target_include_directories(kms_message SYSTEM PRIVATE "${OPENSSL_INCLUDE_DIR}") target_link_libraries(kms_message_static "${OPENSSL_LIBRARIES}") - target_include_directories(kms_message_static PRIVATE "${OPENSSL_INCLUDE_DIR}") + target_include_directories(kms_message_static SYSTEM PRIVATE "${OPENSSL_INCLUDE_DIR}") endif() endif () @@ -259,7 +267,7 @@ if (NOT DISABLE_NATIVE_CRYPTO) else() include (FindOpenSSL) target_link_libraries(test_kms_request "${OPENSSL_LIBRARIES}") - target_include_directories(test_kms_request PRIVATE "${OPENSSL_INCLUDE_DIR}") + target_include_directories(test_kms_request SYSTEM PRIVATE "${OPENSSL_INCLUDE_DIR}") endif() add_test ( diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_gcp_request.c b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_gcp_request.c index 564cacc..960141b 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_gcp_request.c +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_gcp_request.c @@ -87,7 +87,7 @@ kms_gcp_request_oauth_new (const char *host, req->crypto.sign_ctx = opt->crypto.sign_ctx; } - jwt_signature = malloc (SIGNATURE_LEN); + jwt_signature = calloc (1, SIGNATURE_LEN); if (!req->crypto.sign_rsaes_pkcs1_v1_5 ( req->crypto.sign_ctx, private_key_data, diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c index 08affaa..56ca01f 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c @@ -178,6 +178,14 @@ kmip_writer_write_enumeration (kmip_writer_t *writer, kmip_tag_type_t tag, int32 kmip_writer_write_u32 (writer, 0); } +void kmip_writer_write_bool (kmip_writer_t *writer, kmip_tag_type_t tag, bool value) +{ + kmip_writer_write_tag_enum (writer, tag); + kmip_writer_write_u8 (writer, KMIP_ITEM_TYPE_Boolean); + kmip_writer_write_u32 (writer, 8); + kmip_writer_write_u64(writer, (uint64_t) value); +} + void kmip_writer_write_datetime (kmip_writer_t *writer, kmip_tag_type_t tag, int64_t value) { @@ -384,6 +392,15 @@ kmip_reader_read_enumeration (kmip_reader_t *reader, uint32_t *enum_value) return kmip_reader_read_u32 (reader, &ignored); } +bool +kmip_reader_read_bool (kmip_reader_t *reader, bool *value) +{ + uint64_t u64; + CHECK_AND_RET (kmip_reader_read_u64 (reader, &u64)); + *value = (bool) u64; + return true; +} + bool kmip_reader_read_integer (kmip_reader_t *reader, int32_t *value) { diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_reader_writer_private.h b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_reader_writer_private.h index 314bf39..a31aa1c 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_reader_writer_private.h +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_reader_writer_private.h @@ -59,6 +59,9 @@ kmip_writer_write_long_integer (kmip_writer_t *writer, kmip_tag_type_t tag, int6 void kmip_writer_write_enumeration (kmip_writer_t *writer, kmip_tag_type_t tag, int32_t value); +void +kmip_writer_write_bool (kmip_writer_t *writer, kmip_tag_type_t tag, bool value); + void kmip_writer_write_datetime (kmip_writer_t *writer, kmip_tag_type_t tag, int64_t value); @@ -112,6 +115,9 @@ kmip_reader_read_type (kmip_reader_t *reader, kmip_item_type_t *type); bool kmip_reader_read_enumeration (kmip_reader_t *reader, uint32_t *enum_value); +bool +kmip_reader_read_bool (kmip_reader_t *reader, bool *value); + bool kmip_reader_read_integer (kmip_reader_t *reader, int32_t *value); diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_request.c b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_request.c index c59bff7..3b95410 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_request.c +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_request.c @@ -16,6 +16,7 @@ #include "kms_message/kms_kmip_request.h" +#include "kms_kmip_tag_type_private.h" #include "kms_message_private.h" #include "kms_kmip_reader_writer_private.h" @@ -181,7 +182,7 @@ kms_kmip_request_activate_new (void *reserved, const char *unique_identifer) kmip_writer_close_struct (writer); /* KMIP_TAG_RequestHeader */ kmip_writer_begin_struct (writer, KMIP_TAG_BatchItem); - /* 0x0A == Get */ + /* 0x12 == Activate */ kmip_writer_write_enumeration (writer, KMIP_TAG_Operation, 0x12); kmip_writer_begin_struct (writer, KMIP_TAG_RequestPayload); kmip_writer_write_string (writer, @@ -254,3 +255,212 @@ kms_kmip_request_get_new (void *reserved, const char *unique_identifer) kmip_writer_destroy (writer); return req; } + +kms_request_t * +kms_kmip_request_create_new (void *reserved) { + /* + Create a KMIP Create request of this form: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + */ + kmip_writer_t *writer; + kms_request_t *req; + + req = calloc (1, sizeof (kms_request_t)); + req->provider = KMS_REQUEST_PROVIDER_KMIP; + + writer = kmip_writer_new(); + kmip_writer_begin_struct(writer, KMIP_TAG_RequestMessage); + + kmip_writer_begin_struct (writer, KMIP_TAG_RequestHeader); + kmip_writer_begin_struct (writer, KMIP_TAG_ProtocolVersion); + kmip_writer_write_integer (writer, KMIP_TAG_ProtocolVersionMajor, 1); + kmip_writer_write_integer (writer, KMIP_TAG_ProtocolVersionMinor, 2); + kmip_writer_close_struct (writer); /* KMIP_TAG_ProtocolVersion */ + kmip_writer_write_integer (writer, KMIP_TAG_BatchCount, 1); + kmip_writer_close_struct (writer); /* KMIP_TAG_RequestHeader */ + + kmip_writer_begin_struct (writer, KMIP_TAG_BatchItem); + /* 0x01 == Create */ + kmip_writer_write_enumeration (writer, KMIP_TAG_Operation, 0x01); + kmip_writer_begin_struct (writer, KMIP_TAG_RequestPayload); + /* 0x02 == symmetric key */ + kmip_writer_write_enumeration(writer, KMIP_TAG_ObjectType, 0x02); + + { + kmip_writer_begin_struct (writer, KMIP_TAG_TemplateAttribute); + + kmip_writer_begin_struct (writer, KMIP_TAG_Attribute); + const char *cryptographicAlgorithmStr = "Cryptographic Algorithm"; + kmip_writer_write_string (writer, + KMIP_TAG_AttributeName, + cryptographicAlgorithmStr, + strlen (cryptographicAlgorithmStr)); + kmip_writer_write_enumeration (writer, KMIP_TAG_AttributeValue, 3 /* AES */); + kmip_writer_close_struct (writer); + kmip_writer_begin_struct (writer, KMIP_TAG_Attribute); + const char *cryptographicLengthStr = "Cryptographic Length"; + kmip_writer_write_string (writer, + KMIP_TAG_AttributeName, + cryptographicLengthStr, + strlen (cryptographicLengthStr)); + kmip_writer_write_integer (writer, KMIP_TAG_AttributeValue, 256); + kmip_writer_close_struct (writer); + kmip_writer_begin_struct (writer, KMIP_TAG_Attribute); + const char *cryptographicUsageMaskStr = "Cryptographic Usage Mask"; + kmip_writer_write_string (writer, + KMIP_TAG_AttributeName, + cryptographicUsageMaskStr, + strlen (cryptographicUsageMaskStr)); + kmip_writer_write_integer (writer, KMIP_TAG_AttributeValue, 4 | 8 /* Encrypt | Decrypt */); + kmip_writer_close_struct (writer); + + kmip_writer_close_struct (writer); /* KMIP_TAG_TemplateAttribute */ + } + + kmip_writer_close_struct (writer); /* KMIP_TAG_RequestPayload */ + kmip_writer_close_struct (writer); /* KMIP_TAG_BatchItem */ + kmip_writer_close_struct (writer); /* KMIP_TAG_RequestMessage */ + + /* Copy the KMIP writer buffer to a KMIP request. */ + copy_writer_buffer (req, writer); + kmip_writer_destroy (writer); + return req; +} + +static kms_request_t * +kmip_encrypt_decrypt (const char* unique_identifer, const uint8_t *data, size_t len, + const uint8_t *iv_data, size_t iv_len, bool encrypt) { + kmip_writer_t *writer; + kms_request_t *req; + + req = calloc (1, sizeof (kms_request_t)); + req->provider = KMS_REQUEST_PROVIDER_KMIP; + + writer = kmip_writer_new(); + kmip_writer_begin_struct(writer, KMIP_TAG_RequestMessage); + + kmip_writer_begin_struct (writer, KMIP_TAG_RequestHeader); + kmip_writer_begin_struct (writer, KMIP_TAG_ProtocolVersion); + kmip_writer_write_integer (writer, KMIP_TAG_ProtocolVersionMajor, 1); + kmip_writer_write_integer (writer, KMIP_TAG_ProtocolVersionMinor, 2); + kmip_writer_close_struct (writer); /* KMIP_TAG_ProtocolVersion */ + kmip_writer_write_integer (writer, KMIP_TAG_BatchCount, 1); + kmip_writer_close_struct (writer); /* KMIP_TAG_RequestHeader */ + + kmip_writer_begin_struct (writer, KMIP_TAG_BatchItem); + /* 0x1F == Encrypt, 0x20 == Decrypt*/ + kmip_writer_write_enumeration (writer, KMIP_TAG_Operation, encrypt ? 0x1F : 0x20); + kmip_writer_begin_struct (writer, KMIP_TAG_RequestPayload); + kmip_writer_write_string (writer, + KMIP_TAG_UniqueIdentifier, + unique_identifer, + strlen (unique_identifer)); + + kmip_writer_begin_struct (writer, KMIP_TAG_CryptographicParameters); + kmip_writer_write_enumeration(writer, KMIP_TAG_BlockCipherMode, 1 /* CBC */); + kmip_writer_write_enumeration(writer, KMIP_TAG_PaddingMethod, 3 /* PKCS5 */); + kmip_writer_write_enumeration(writer, KMIP_TAG_CryptographicAlgorithm, 3 /* AES */); + if (encrypt) kmip_writer_write_bool(writer, KMIP_TAG_RandomIV, true); + kmip_writer_close_struct(writer); /* KMIP_TAG_CryptographicParameters */ + + kmip_writer_write_bytes(writer, KMIP_TAG_Data, (char *) data, len); + if (!encrypt) kmip_writer_write_bytes(writer, KMIP_TAG_IVCounterNonce, (char *) iv_data, iv_len); + + kmip_writer_close_struct (writer); /* KMIP_TAG_RequestPayload */ + kmip_writer_close_struct (writer); /* KMIP_TAG_BatchItem */ + kmip_writer_close_struct (writer); /* KMIP_TAG_RequestMessage */ + + /* Copy the KMIP writer buffer to a KMIP request. */ + copy_writer_buffer (req, writer); + kmip_writer_destroy (writer); + return req; +} + +kms_request_t * +kms_kmip_request_encrypt_new (void *reserved, const char* unique_identifer, const uint8_t *plaintext, size_t len) { + /* + Create a KMIP Encrypt request of this form: + + + + + + + + + + + + + + + + + + + + + + + */ + return kmip_encrypt_decrypt(unique_identifer, plaintext, len, NULL, 0, true); +} + +kms_request_t * +kms_kmip_request_decrypt_new (void *reserved, const char* unique_identifer, const uint8_t *ciphertext, size_t len, const uint8_t *iv_data, size_t iv_len) { + /* + Create a KMIP Decrypt request of this form: + + + + + + + + + + + + + + + + + + + + + + + */ + return kmip_encrypt_decrypt(unique_identifer, ciphertext, len, iv_data, iv_len, false); +} + diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_response.c b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_response.c index b4dc2c6..ec389e6 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_response.c +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_response.c @@ -1,5 +1,7 @@ #include "kms_message/kms_kmip_response.h" +#include "kms_kmip_item_type_private.h" +#include "kms_kmip_tag_type_private.h" #include "kms_message_private.h" #include "kms_kmip_reader_writer_private.h" #include "kms_kmip_result_reason_private.h" @@ -209,6 +211,167 @@ kms_kmip_response_get_unique_identifier (kms_response_t *res) return kms_request_str_detach (nullterminated); } +/* +Example of a successful response to an Encrypt request: + + + + + + + + + + + + + + + + + + + +*/ +uint8_t * +kms_kmip_response_get_iv (kms_response_t *res, size_t *datalen) { + kmip_reader_t *reader = NULL; + size_t pos; + size_t len; + uint8_t *data = NULL; + uint8_t *tmp; + + if (!check_and_require_kmip (res)) { + goto fail; + } + + if (!kms_kmip_response_ok (res)) { + goto fail; + } + + reader = kmip_reader_new (res->kmip.data, res->kmip.len); + + if (!kmip_reader_find_and_recurse (reader, KMIP_TAG_ResponseMessage)) { + KMS_ERROR (res, + "unable to find tag: %s", + kmip_tag_to_string (KMIP_TAG_ResponseMessage)); + goto fail; + } + + if (!kmip_reader_find_and_recurse (reader, KMIP_TAG_BatchItem)) { + KMS_ERROR (res, + "unable to find tag: %s", + kmip_tag_to_string (KMIP_TAG_BatchItem)); + goto fail; + } + + if (!kmip_reader_find_and_recurse (reader, KMIP_TAG_ResponsePayload)) { + KMS_ERROR (res, + "unable to find tag: %s", + kmip_tag_to_string (KMIP_TAG_ResponsePayload)); + goto fail; + } + + if (!kmip_reader_find (reader, KMIP_TAG_IVCounterNonce, KMIP_ITEM_TYPE_ByteString, &pos, &len)) { + KMS_ERROR (res, + "unable to find tag: %s", + kmip_tag_to_string (KMIP_TAG_Data)); + goto fail; + } + + if (!kmip_reader_read_bytes (reader, &tmp, len)) { + KMS_ERROR (res, "unable to read data bytes"); + goto fail; + } + data = malloc (len); + memcpy (data, tmp, len); + *datalen = len; + + fail: + kmip_reader_destroy (reader); + return data; +} + +/* +Example of a successful response to a Decrypt request: + + + + + + + + + + + + + + + + + + +*/ +uint8_t * +kms_kmip_response_get_data (kms_response_t *res, size_t *datalen) { + kmip_reader_t *reader = NULL; + size_t pos; + size_t len; + uint8_t *data = NULL; + uint8_t *tmp; + + if (!check_and_require_kmip (res)) { + goto fail; + } + + if (!kms_kmip_response_ok (res)) { + goto fail; + } + + reader = kmip_reader_new (res->kmip.data, res->kmip.len); + + if (!kmip_reader_find_and_recurse (reader, KMIP_TAG_ResponseMessage)) { + KMS_ERROR (res, + "unable to find tag: %s", + kmip_tag_to_string (KMIP_TAG_ResponseMessage)); + goto fail; + } + + if (!kmip_reader_find_and_recurse (reader, KMIP_TAG_BatchItem)) { + KMS_ERROR (res, + "unable to find tag: %s", + kmip_tag_to_string (KMIP_TAG_BatchItem)); + goto fail; + } + + if (!kmip_reader_find_and_recurse (reader, KMIP_TAG_ResponsePayload)) { + KMS_ERROR (res, + "unable to find tag: %s", + kmip_tag_to_string (KMIP_TAG_ResponsePayload)); + goto fail; + } + + if (!kmip_reader_find (reader, KMIP_TAG_Data, KMIP_ITEM_TYPE_ByteString, &pos, &len)) { + KMS_ERROR (res, + "unable to find tag: %s", + kmip_tag_to_string (KMIP_TAG_Data)); + goto fail; + } + + if (!kmip_reader_read_bytes (reader, &tmp, len)) { + KMS_ERROR (res, "unable to read data bytes"); + goto fail; + } + data = malloc (len); + memcpy (data, tmp, len); + *datalen = len; + + fail: + kmip_reader_destroy (reader); + return data; +} + /* Example of a successful response to a Get request: diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_tag_type_private.h b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_tag_type_private.h index 293ff15..91df9f9 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_tag_type_private.h +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_tag_type_private.h @@ -312,7 +312,8 @@ KMS_X (AlwaysSensitive, 0x420121) \ KMS_X (Extractable, 0x420122) \ KMS_X (NeverExtractable, 0x420123) \ - KMS_X_LAST (ReplaceExisting, 0x420124) + KMS_X (ReplaceExisting, 0x420124) \ + KMS_X_LAST (Attributes, 0x420125) /* clang-format on */ /* Generate an enum with each tag value. */ diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_kmip_request.h b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_kmip_request.h index 68eac81..c688ebc 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_kmip_request.h +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_kmip_request.h @@ -51,6 +51,23 @@ kms_kmip_request_activate_new (void *reserved, const char *unique_identifier); KMS_MSG_EXPORT (kms_request_t *) kms_kmip_request_get_new (void *reserved, const char *unique_identifier); +KMS_MSG_EXPORT (kms_request_t *) +kms_kmip_request_create_new (void *reserved); + +KMS_MSG_EXPORT (kms_request_t *) +kms_kmip_request_encrypt_new (void *reserved, + const char *unique_identifier, + const uint8_t *plaintext, + size_t len); + +KMS_MSG_EXPORT (kms_request_t *) +kms_kmip_request_decrypt_new (void *reserved, + const char *unique_identifier, + const uint8_t *ciphertext, + size_t len, + const uint8_t *iv, + size_t iv_len); + #ifdef __cplusplus } #endif diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_kmip_response.h b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_kmip_response.h index 4c24c51..a29a87f 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_kmip_response.h +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message/kms_kmip_response.h @@ -37,4 +37,10 @@ kms_kmip_response_get_unique_identifier (kms_response_t *res); KMS_MSG_EXPORT (uint8_t *) kms_kmip_response_get_secretdata (kms_response_t *res, size_t *secretdatalen); +KMS_MSG_EXPORT (uint8_t *) +kms_kmip_response_get_data (kms_response_t *res, size_t *datalen); + +KMS_MSG_EXPORT (uint8_t *) +kms_kmip_response_get_iv (kms_response_t *res, size_t *datalen); + #endif /* KMS_KMIP_RESPONSE_H */ diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_port.c b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_port.c index ee9e6ed..cf5f52f 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_port.c +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_port.c @@ -18,7 +18,8 @@ #if defined(_WIN32) #include #include -char * kms_strndup (const char *src, size_t len) +char * +kms_strndup (const char *src, size_t len) { char *dst = (char *) malloc (len + 1); if (!dst) { @@ -30,4 +31,4 @@ char * kms_strndup (const char *src, size_t len) return dst; } -#endif \ No newline at end of file +#endif diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request.c b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request.c index d0978d6..86f90a1 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request.c +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request.c @@ -181,10 +181,12 @@ kms_request_set_date (kms_request_t *request, const struct tm *tm) /* use current time */ time_t t; time (&t); -#ifdef _WIN32 +#if defined(KMS_MESSAGE_HAVE_GMTIME_R) + gmtime_r (&t, &tmp_tm); +#elif defined(_MSC_VER) gmtime_s (&tmp_tm, &t); #else - gmtime_r (&t, &tmp_tm); + tmp_tm = *gmtime (&t); #endif tm = &tmp_tm; } diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request_str.c b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request_str.c index 48ab810..57b2e4f 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request_str.c +++ b/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request_str.c @@ -328,7 +328,7 @@ kms_request_str_append_stripped (kms_request_str_t *str, kms_request_str_reserve (str, appended->len); - // msvcrt is unhappy when it gets non-ANSI characters in isspace + /* msvcrt is unhappy when it gets non-ANSI characters in isspace */ while (*src >= 0 && isspace (*src)) { ++src; } @@ -366,7 +366,7 @@ kms_request_str_append_hashed (_kms_crypto_t *crypto, kms_request_str_t *str, kms_request_str_t *appended) { - uint8_t hash[32]; + uint8_t hash[32] = {0}; char *hex_chars; if (!crypto->sha256 (crypto->ctx, appended->str, appended->len, hash)) { diff --git a/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kmip_reader_writer.c b/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kmip_reader_writer.c index ed053a6..bb2973f 100644 --- a/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kmip_reader_writer.c +++ b/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kmip_reader_writer.c @@ -88,7 +88,13 @@ kms_kmip_writer_test (void) "An Enumeration with value 255"); kmip_writer_destroy (writer); - /* Boolean is not implemented. */ + writer = kmip_writer_new (); + kmip_writer_write_bool (writer, KMIP_TAG_CompromiseDate, true); + kms_kmip_writer_test_evaluate ( + writer, + "42 00 20 | 06 | 00 00 00 08 | 00 00 00 00 00 00 00 01", + "An boolean containing the value true"); + kmip_writer_destroy (writer); writer = kmip_writer_new (); kmip_writer_write_string ( @@ -147,6 +153,7 @@ kms_kmip_reader_test (void) int64_t i64; uint32_t u32; uint8_t *ptr; + bool b; /* The following test cases come from section 9.1.2 of * http://docs.oasis-open.org/kmip/spec/v1.4/os/kmip-spec-v1.4-os.html */ @@ -200,7 +207,21 @@ kms_kmip_reader_test (void) kmip_reader_destroy (reader); free (data); - /* Boolean is not implemented */ + /* A boolean with value true */ + data = hex_to_data ("42 00 20 | 06 | 00 00 00 08 | 00 00 00 00 00 00 00 01", + &datalen); + reader = kmip_reader_new (data, datalen); + ASSERT (kmip_reader_read_tag (reader, &tag)); + ASSERT (tag == KMIP_TAG_CompromiseDate); + ASSERT (kmip_reader_read_type (reader, &type)); + ASSERT (type == KMIP_ITEM_TYPE_Boolean); + ASSERT (kmip_reader_read_length (reader, &length)); + ASSERT (length == 8); + ASSERT (kmip_reader_read_bool (reader, &b)); + ASSERT (b); + ASSERT (!kmip_reader_has_data (reader)); + kmip_reader_destroy (reader); + free (data); /* A Text String with the value 'Hello World' */ data = hex_to_data ("42 00 20 | 07 | 00 00 00 0B | 48 65 6C " diff --git a/ext/libmongocrypt/libmongocrypt/src/crypto/libcrypto.c b/ext/libmongocrypt/libmongocrypt/src/crypto/libcrypto.c index dd1b578..2fee384 100644 --- a/ext/libmongocrypt/libmongocrypt/src/crypto/libcrypto.c +++ b/ext/libmongocrypt/libmongocrypt/src/crypto/libcrypto.c @@ -61,7 +61,7 @@ void _native_crypto_init(void) { static bool _encrypt_with_cipher(const EVP_CIPHER *cipher, aes_256_args_t args) { EVP_CIPHER_CTX *ctx; bool ret = false; - int intermediate_bytes_written; + int intermediate_bytes_written = 0; mongocrypt_status_t *status = args.status; ctx = EVP_CIPHER_CTX_new(); @@ -71,8 +71,8 @@ static bool _encrypt_with_cipher(const EVP_CIPHER *cipher, aes_256_args_t args) BSON_ASSERT(args.out); BSON_ASSERT(ctx); BSON_ASSERT(cipher); - BSON_ASSERT(NULL == args.iv || EVP_CIPHER_iv_length(cipher) == args.iv->len); - BSON_ASSERT(EVP_CIPHER_key_length(cipher) == args.key->len); + BSON_ASSERT(NULL == args.iv || (uint32_t)EVP_CIPHER_iv_length(cipher) == args.iv->len); + BSON_ASSERT((uint32_t)EVP_CIPHER_key_length(cipher) == args.key->len); BSON_ASSERT(args.in->len <= INT_MAX); if (!EVP_EncryptInit_ex(ctx, cipher, NULL /* engine */, args.key->data, NULL == args.iv ? NULL : args.iv->data)) { @@ -89,6 +89,7 @@ static bool _encrypt_with_cipher(const EVP_CIPHER *cipher, aes_256_args_t args) goto done; } + BSON_ASSERT(intermediate_bytes_written >= 0 && (uint64_t)intermediate_bytes_written <= UINT32_MAX); /* intermediate_bytes_written cannot be negative, so int -> uint32_t is OK */ *args.bytes_written = (uint32_t)intermediate_bytes_written; @@ -97,7 +98,7 @@ static bool _encrypt_with_cipher(const EVP_CIPHER *cipher, aes_256_args_t args) goto done; } - BSON_ASSERT(UINT32_MAX - *args.bytes_written >= intermediate_bytes_written); + BSON_ASSERT(UINT32_MAX - *args.bytes_written >= (uint32_t)intermediate_bytes_written); *args.bytes_written += (uint32_t)intermediate_bytes_written; ret = true; @@ -116,18 +117,19 @@ static bool _encrypt_with_cipher(const EVP_CIPHER *cipher, aes_256_args_t args) static bool _decrypt_with_cipher(const EVP_CIPHER *cipher, aes_256_args_t args) { EVP_CIPHER_CTX *ctx; bool ret = false; - int intermediate_bytes_written; + int intermediate_bytes_written = 0; mongocrypt_status_t *status = args.status; ctx = EVP_CIPHER_CTX_new(); + BSON_ASSERT(ctx); BSON_ASSERT_PARAM(cipher); BSON_ASSERT(args.iv); BSON_ASSERT(args.key); BSON_ASSERT(args.in); BSON_ASSERT(args.out); - BSON_ASSERT(EVP_CIPHER_iv_length(cipher) == args.iv->len); - BSON_ASSERT(EVP_CIPHER_key_length(cipher) == args.key->len); + BSON_ASSERT((uint32_t)EVP_CIPHER_iv_length(cipher) == args.iv->len); + BSON_ASSERT((uint32_t)EVP_CIPHER_key_length(cipher) == args.key->len); BSON_ASSERT(args.in->len <= INT_MAX); if (!EVP_DecryptInit_ex(ctx, cipher, NULL /* engine */, args.key->data, args.iv->data)) { @@ -145,6 +147,7 @@ static bool _decrypt_with_cipher(const EVP_CIPHER *cipher, aes_256_args_t args) goto done; } + BSON_ASSERT(intermediate_bytes_written >= 0 && (uint64_t)intermediate_bytes_written <= UINT32_MAX); /* intermediate_bytes_written cannot be negative, so int -> uint32_t is OK */ *args.bytes_written = (uint32_t)intermediate_bytes_written; @@ -153,7 +156,7 @@ static bool _decrypt_with_cipher(const EVP_CIPHER *cipher, aes_256_args_t args) goto done; } - BSON_ASSERT(UINT32_MAX - *args.bytes_written >= intermediate_bytes_written); + BSON_ASSERT(UINT32_MAX - *args.bytes_written >= (uint32_t)intermediate_bytes_written); *args.bytes_written += (uint32_t)intermediate_bytes_written; ret = true; @@ -203,9 +206,9 @@ static bool _hmac_with_hash(const EVP_MD *hash, ctx = HMAC_CTX_new(); - if (out->len != EVP_MD_size(hash)) { + if (out->len != (uint32_t)EVP_MD_size(hash)) { CLIENT_ERR("out does not contain %d bytes", EVP_MD_size(hash)); - return false; + goto done; } if (!HMAC_Init_ex(ctx, key->data, (int)key->len, hash, NULL /* engine */)) { diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-dec128.h b/ext/libmongocrypt/libmongocrypt/src/mc-dec128.h index 4495714..fd99487 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-dec128.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-dec128.h @@ -607,7 +607,7 @@ static inline char *mc_dec128_to_new_decimal_string(mc_dec128 d) { } } -static inline mc_dec128 mc_dec128_from_bson_iter(bson_iter_t *it) { +static inline mc_dec128 mc_dec128_from_bson_iter(const bson_iter_t *it) { bson_decimal128_t b; if (!bson_iter_decimal128(it, &b)) { mc_dec128 nan = MC_DEC128_POSITIVE_NAN; diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-efc-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-efc-private.h index c4ff806..f9e5c59 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-efc-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-efc-private.h @@ -19,8 +19,19 @@ #include "mongocrypt-buffer-private.h" #include +typedef enum _supported_query_type_flags { + // No queries supported + SUPPORTS_NO_QUERIES = 0, + // Equality query supported + SUPPORTS_EQUALITY_QUERIES = 1 << 0, + // Range query supported + SUPPORTS_RANGE_QUERIES = 1 << 1, + // Range preview query supported + SUPPORTS_RANGE_PREVIEW_DEPRECATED_QUERIES = 1 << 2, +} supported_query_type_flags; + typedef struct _mc_EncryptedField_t { - bool has_queries; + supported_query_type_flags supported_queries; _mongocrypt_buffer_t keyId; const char *path; struct _mc_EncryptedField_t *next; @@ -37,7 +48,10 @@ typedef struct { * into @efc. Fields are copied from @efc_bson. It is OK to free efc_bson after * this call. Fields are appended in reverse order to @efc->fields. Extra * unrecognized fields are not considered an error for forward compatibility. */ -bool mc_EncryptedFieldConfig_parse(mc_EncryptedFieldConfig_t *efc, const bson_t *efc_bson, mongocrypt_status_t *status); +bool mc_EncryptedFieldConfig_parse(mc_EncryptedFieldConfig_t *efc, + const bson_t *efc_bson, + mongocrypt_status_t *status, + bool use_range_v2); void mc_EncryptedFieldConfig_cleanup(mc_EncryptedFieldConfig_t *efc); diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-efc.c b/ext/libmongocrypt/libmongocrypt/src/mc-efc.c index dd75e0f..1a5e6f7 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-efc.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-efc.c @@ -16,12 +16,64 @@ #include "mc-efc-private.h" +#include "mlib/str.h" #include "mongocrypt-private.h" #include "mongocrypt-util-private.h" // mc_iter_document_as_bson +static bool _parse_query_type_string(const char *queryType, supported_query_type_flags *out) { + BSON_ASSERT_PARAM(queryType); + BSON_ASSERT_PARAM(out); + + mstr_view qtv = mstrv_view_cstr(queryType); + + if (mstr_eq_ignore_case(mstrv_lit(MONGOCRYPT_QUERY_TYPE_EQUALITY_STR), qtv)) { + *out = SUPPORTS_EQUALITY_QUERIES; + } else if (mstr_eq_ignore_case(mstrv_lit(MONGOCRYPT_QUERY_TYPE_RANGE_STR), qtv)) { + *out = SUPPORTS_RANGE_QUERIES; + } else if (mstr_eq_ignore_case(mstrv_lit(MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED_STR), qtv)) { + *out = SUPPORTS_RANGE_PREVIEW_DEPRECATED_QUERIES; + } else { + return false; + } + + return true; +} + +static bool +_parse_supported_query_types(bson_iter_t *iter, supported_query_type_flags *out, mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(iter); + BSON_ASSERT_PARAM(out); + if (!BSON_ITER_HOLDS_DOCUMENT(iter)) { + CLIENT_ERR("When parsing supported query types: Expected type document, got: %d", bson_iter_type(iter)); + return false; + } + + bson_t query_doc; + if (!mc_iter_document_as_bson(iter, &query_doc, status)) { + return false; + } + bson_iter_t query_type_iter; + if (!bson_iter_init_find(&query_type_iter, &query_doc, "queryType")) { + CLIENT_ERR("When parsing supported query types: Unable to find 'queryType' in query document"); + return false; + } + if (!BSON_ITER_HOLDS_UTF8(&query_type_iter)) { + CLIENT_ERR("When parsing supported query types: Expected 'queryType' to be type UTF-8, got: %d", + bson_iter_type(&query_type_iter)); + return false; + } + const char *queryType = bson_iter_utf8(&query_type_iter, NULL /* length */); + if (!_parse_query_type_string(queryType, out)) { + CLIENT_ERR("When parsing supported query types: Did not recognize query type '%s'", queryType); + return false; + } + return true; +} + /* _parse_field parses and prepends one field document to efc->fields. */ -static bool _parse_field(mc_EncryptedFieldConfig_t *efc, bson_t *field, mongocrypt_status_t *status) { - bool has_queries = false; +static bool +_parse_field(mc_EncryptedFieldConfig_t *efc, bson_t *field, mongocrypt_status_t *status, bool use_range_v2) { + supported_query_type_flags query_types = SUPPORTS_NO_QUERIES; bson_iter_t field_iter; BSON_ASSERT_PARAM(efc); @@ -53,7 +105,42 @@ static bool _parse_field(mc_EncryptedFieldConfig_t *efc, bson_t *field, mongocry field_path = bson_iter_utf8(&field_iter, NULL /* length */); if (bson_iter_init_find(&field_iter, field, "queries")) { - has_queries = true; + if (BSON_ITER_HOLDS_ARRAY(&field_iter)) { + // Multiple queries, iterate through and grab all query types. + uint32_t queries_buf_len; + const uint8_t *queries_buf; + bson_t queries_arr; + bson_iter_array(&field_iter, &queries_buf_len, &queries_buf); + if (!bson_init_static(&queries_arr, queries_buf, queries_buf_len)) { + CLIENT_ERR("Failed to parse 'queries' field"); + return false; + } + + bson_iter_t queries_iter; + bson_iter_init(&queries_iter, &queries_arr); + while (bson_iter_next(&queries_iter)) { + supported_query_type_flags flag; + if (!_parse_supported_query_types(&queries_iter, &flag, status)) { + return false; + } + query_types |= flag; + } + } else { + supported_query_type_flags flag; + if (!_parse_supported_query_types(&field_iter, &flag, status)) { + return false; + } + query_types |= flag; + } + } + + if (query_types & SUPPORTS_RANGE_PREVIEW_DEPRECATED_QUERIES && use_range_v2) { + // When rangev2 is enabled ("range") error if "rangePreview" is included. + // This check is intended to give an easier-to-understand earlier error. + CLIENT_ERR("Cannot use field '%s' with 'rangePreview' queries. 'rangePreview' is unsupported. Use 'range' " + "instead. 'range' is not compatible with 'rangePreview' and requires recreating the collection.", + field_path); + return false; } /* Prepend a new mc_EncryptedField_t */ @@ -61,7 +148,7 @@ static bool _parse_field(mc_EncryptedFieldConfig_t *efc, bson_t *field, mongocry _mongocrypt_buffer_copy_to(&field_keyid, &ef->keyId); ef->path = bson_strdup(field_path); ef->next = efc->fields; - ef->has_queries = has_queries; + ef->supported_queries = query_types; efc->fields = ef; return true; @@ -69,7 +156,8 @@ static bool _parse_field(mc_EncryptedFieldConfig_t *efc, bson_t *field, mongocry bool mc_EncryptedFieldConfig_parse(mc_EncryptedFieldConfig_t *efc, const bson_t *efc_bson, - mongocrypt_status_t *status) { + mongocrypt_status_t *status, + bool use_range_v2) { bson_iter_t iter; BSON_ASSERT_PARAM(efc); @@ -93,7 +181,7 @@ bool mc_EncryptedFieldConfig_parse(mc_EncryptedFieldConfig_t *efc, if (!mc_iter_document_as_bson(&iter, &field, status)) { return false; } - if (!_parse_field(efc, &field, status)) { + if (!_parse_field(efc, &field, status, use_range_v2)) { return false; } } diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h index d1ec121..3e26ec6 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h @@ -49,7 +49,9 @@ typedef struct { bson_iter_t indexMax; // precision determines the number of digits after the decimal point for // floating point values. - mc_optional_uint32_t precision; + mc_optional_int32_t precision; + // trimFactor determines how many root levels of the hypergraph to trim. + mc_optional_int32_t trimFactor; } mc_FLE2RangeFindSpecEdgesInfo_t; /** FLE2RangeFindSpec represents the range find specification that is encoded @@ -74,7 +76,10 @@ typedef struct { mc_FLE2RangeOperator_t secondOperator; } mc_FLE2RangeFindSpec_t; -bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status); +bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, + const bson_iter_t *in, + bool use_range_v2, + mongocrypt_status_t *status); /** mc_FLE2RangeInsertSpec_t represents the range insert specification that is * encoded inside of a FLE2EncryptionPlaceholder. See @@ -89,10 +94,15 @@ typedef struct { bson_iter_t max; // precision determines the number of digits after the decimal point for // floating point values. - mc_optional_uint32_t precision; + mc_optional_int32_t precision; + // trimFactor determines how many root levels of the hypergraph to trim. + mc_optional_int32_t trimFactor; } mc_FLE2RangeInsertSpec_t; -bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status); +bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, + const bson_iter_t *in, + bool use_range_v2, + mongocrypt_status_t *status); /** FLE2EncryptionPlaceholder implements Encryption BinData (subtype 6) * sub-subtype 0, the intent-to-encrypt mapping. Contains a value to encrypt and @@ -116,7 +126,7 @@ typedef struct { bson_iter_t v_iter; _mongocrypt_buffer_t index_key_id; _mongocrypt_buffer_t user_key_id; - int64_t maxContentionCounter; + int64_t maxContentionFactor; // sparsity is the Queryable Encryption range hypergraph sparsity factor int64_t sparsity; } mc_FLE2EncryptionPlaceholder_t; diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder.c index 4a63b6b..fc839b8 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder.c @@ -22,11 +22,14 @@ #include "mongocrypt-buffer-private.h" #include "mongocrypt.h" +#define CLIENT_ERR_PREFIXED_HELPER(Prefix, ErrorString, ...) CLIENT_ERR(Prefix ": " ErrorString, ##__VA_ARGS__) +#define CLIENT_ERR_PREFIXED(ErrorString, ...) CLIENT_ERR_PREFIXED_HELPER(ERROR_PREFIX, ErrorString, ##__VA_ARGS__) + // Common logic for testing field name, tracking duplication, and presence. #define IF_FIELD(Name) \ if (0 == strcmp(field, #Name)) { \ if (has_##Name) { \ - CLIENT_ERR("Duplicate field '" #Name "' in placeholder bson"); \ + CLIENT_ERR_PREFIXED("Duplicate field '" #Name "' in placeholder bson"); \ goto fail; \ } \ has_##Name = true; @@ -37,7 +40,7 @@ #define CHECK_HAS(Name) \ if (!has_##Name) { \ - CLIENT_ERR("Missing field '" #Name "' in placeholder"); \ + CLIENT_ERR_PREFIXED("Missing field '" #Name "' in placeholder"); \ goto fail; \ } @@ -45,10 +48,12 @@ void mc_FLE2EncryptionPlaceholder_init(mc_FLE2EncryptionPlaceholder_t *placehold memset(placeholder, 0, sizeof(mc_FLE2EncryptionPlaceholder_t)); } +#define ERROR_PREFIX "Error parsing FLE2EncryptionPlaceholder" + bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out, const bson_t *in, mongocrypt_status_t *status) { - bson_iter_t iter; + bson_iter_t iter = {0}; bool has_t = false, has_a = false, has_v = false, has_cm = false; bool has_ki = false, has_ku = false; bool has_s = false; @@ -58,7 +63,7 @@ bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out, mc_FLE2EncryptionPlaceholder_init(out); if (!bson_validate(in, BSON_VALIDATE_NONE, NULL) || !bson_iter_init(&iter, in)) { - CLIENT_ERR("invalid BSON"); + CLIENT_ERR_PREFIXED("invalid BSON"); return false; } @@ -69,12 +74,12 @@ bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out, IF_FIELD(t) { int32_t type; if (!BSON_ITER_HOLDS_INT32(&iter)) { - CLIENT_ERR("invalid marking, 't' must be an int32"); + CLIENT_ERR_PREFIXED("invalid marking, 't' must be an int32"); goto fail; } type = bson_iter_int32(&iter); if ((type != MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT) && (type != MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND)) { - CLIENT_ERR("invalid placeholder type value: %d", type); + CLIENT_ERR_PREFIXED("invalid placeholder type value: %d", type); goto fail; } out->type = (mongocrypt_fle2_placeholder_type_t)type; @@ -84,13 +89,13 @@ bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out, IF_FIELD(a) { int32_t algorithm; if (!BSON_ITER_HOLDS_INT32(&iter)) { - CLIENT_ERR("invalid marking, 'a' must be an int32"); + CLIENT_ERR_PREFIXED("invalid marking, 'a' must be an int32"); goto fail; } algorithm = bson_iter_int32(&iter); if (algorithm != MONGOCRYPT_FLE2_ALGORITHM_UNINDEXED && algorithm != MONGOCRYPT_FLE2_ALGORITHM_EQUALITY && algorithm != MONGOCRYPT_FLE2_ALGORITHM_RANGE) { - CLIENT_ERR("invalid algorithm value: %d", algorithm); + CLIENT_ERR_PREFIXED("invalid algorithm value: %d", algorithm); goto fail; } out->algorithm = (mongocrypt_fle2_encryption_algorithm_t)algorithm; @@ -99,7 +104,7 @@ bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out, IF_FIELD(ki) { if (!_mongocrypt_buffer_from_uuid_iter(&out->index_key_id, &iter)) { - CLIENT_ERR("index key id must be a UUID"); + CLIENT_ERR_PREFIXED("index key id must be a UUID"); goto fail; } } @@ -107,7 +112,7 @@ bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out, IF_FIELD(ku) { if (!_mongocrypt_buffer_from_uuid_iter(&out->user_key_id, &iter)) { - CLIENT_ERR("user key id must be a UUID"); + CLIENT_ERR_PREFIXED("user key id must be a UUID"); goto fail; } } @@ -120,11 +125,11 @@ bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out, IF_FIELD(cm) { if (!BSON_ITER_HOLDS_INT64(&iter)) { - CLIENT_ERR("invalid marking, 'cm' must be an int64"); + CLIENT_ERR_PREFIXED("invalid marking, 'cm' must be an int64"); goto fail; } - out->maxContentionCounter = bson_iter_int64(&iter); - if (!mc_validate_contention(out->maxContentionCounter, status)) { + out->maxContentionFactor = bson_iter_int64(&iter); + if (!mc_validate_contention(out->maxContentionFactor, status)) { goto fail; } } @@ -132,7 +137,7 @@ bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out, IF_FIELD(s) { if (!BSON_ITER_HOLDS_INT64(&iter)) { - CLIENT_ERR("invalid marking, 's' must be an int64"); + CLIENT_ERR_PREFIXED("invalid marking, 's' must be an int64"); goto fail; } out->sparsity = bson_iter_int64(&iter); @@ -168,37 +173,47 @@ void mc_FLE2EncryptionPlaceholder_cleanup(mc_FLE2EncryptionPlaceholder_t *placeh mc_FLE2EncryptionPlaceholder_init(placeholder); } +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error validating contention" + bool mc_validate_contention(int64_t contention, mongocrypt_status_t *status) { if (contention < 0) { - CLIENT_ERR("contention must be non-negative, got: %" PRId64, contention); + CLIENT_ERR_PREFIXED("contention must be non-negative, got: %" PRId64, contention); return false; } if (contention == INT64_MAX) { - CLIENT_ERR("contention must be < INT64_MAX, got: %" PRId64, contention); + CLIENT_ERR_PREFIXED("contention must be < INT64_MAX, got: %" PRId64, contention); return false; } return true; } +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error validating sparsity" + bool mc_validate_sparsity(int64_t sparsity, mongocrypt_status_t *status) { if (sparsity < 0) { - CLIENT_ERR("sparsity must be non-negative, got: %" PRId64, sparsity); + CLIENT_ERR_PREFIXED("sparsity must be non-negative, got: %" PRId64, sparsity); return false; } // mc_getEdgesInt expects a size_t sparsity. - if (sparsity >= SIZE_MAX) { - CLIENT_ERR("sparsity must be < %zu, got: %" PRId64, SIZE_MAX, sparsity); + if ((uint64_t)sparsity >= SIZE_MAX) { + CLIENT_ERR_PREFIXED("sparsity must be < %zu, got: %" PRId64, SIZE_MAX, sparsity); return false; } return true; } +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error parsing FLE2RangeFindSpecEdgesInfo" + static bool mc_FLE2RangeFindSpecEdgesInfo_parse(mc_FLE2RangeFindSpecEdgesInfo_t *out, const bson_iter_t *in, + bool use_range_v2, mongocrypt_status_t *status) { bson_iter_t iter; bool has_lowerBound = false, has_lbIncluded = false, has_upperBound = false, has_ubIncluded = false, - has_indexMin = false, has_indexMax = false, has_precision = false; + has_indexMin = false, has_indexMax = false, has_precision = false, has_trimFactor = false; BSON_ASSERT_PARAM(out); BSON_ASSERT_PARAM(in); @@ -206,8 +221,7 @@ static bool mc_FLE2RangeFindSpecEdgesInfo_parse(mc_FLE2RangeFindSpecEdgesInfo_t iter = *in; if (!BSON_ITER_HOLDS_DOCUMENT(&iter)) { - CLIENT_ERR("invalid FLE2RangeFindSpecEdgesInfo: must be an iterator to " - "a document"); + CLIENT_ERR_PREFIXED("must be an iterator to a document"); return false; } bson_iter_recurse(&iter, &iter); @@ -223,8 +237,7 @@ static bool mc_FLE2RangeFindSpecEdgesInfo_parse(mc_FLE2RangeFindSpecEdgesInfo_t IF_FIELD(lbIncluded) { if (!BSON_ITER_HOLDS_BOOL(&iter)) { - CLIENT_ERR("invalid FLE2RangeFindSpecEdgesInfo: 'lbIncluded' must " - "be a bool"); + CLIENT_ERR_PREFIXED("'lbIncluded' must be a bool"); goto fail; } out->lbIncluded = bson_iter_bool(&iter); @@ -238,8 +251,7 @@ static bool mc_FLE2RangeFindSpecEdgesInfo_parse(mc_FLE2RangeFindSpecEdgesInfo_t IF_FIELD(ubIncluded) { if (!BSON_ITER_HOLDS_BOOL(&iter)) { - CLIENT_ERR("invalid FLE2RangeFindSpecEdgesInfo: 'ubIncluded' must " - "be a bool"); + CLIENT_ERR_PREFIXED("'ubIncluded' must be a bool"); goto fail; } out->ubIncluded = bson_iter_bool(&iter); @@ -258,18 +270,31 @@ static bool mc_FLE2RangeFindSpecEdgesInfo_parse(mc_FLE2RangeFindSpecEdgesInfo_t IF_FIELD(precision) { if (!BSON_ITER_HOLDS_INT32(&iter)) { - CLIENT_ERR("invalid FLE2RangeFindSpecEdgesInfo: 'precision' must " - "be an int32"); + CLIENT_ERR_PREFIXED("'precision' must be an int32"); goto fail; } int32_t val = bson_iter_int32(&iter); if (val < 0) { - CLIENT_ERR("invalid FLE2RangeFindSpecEdgesInfo: 'precision' must be" - "non-negative"); + CLIENT_ERR_PREFIXED("'precision' must be non-negative"); goto fail; } - out->precision = OPT_U32((uint32_t)val); + out->precision = OPT_I32(val); + } + END_IF_FIELD + + IF_FIELD(trimFactor) { + if (!BSON_ITER_HOLDS_INT32(&iter)) { + CLIENT_ERR_PREFIXED("'trimFactor' must be an int32"); + goto fail; + } + int32_t val = bson_iter_int32(&iter); + if (val < 0) { + CLIENT_ERR_PREFIXED("'trimFactor' must be non-negative"); + goto fail; + } + + out->trimFactor = OPT_I32(val); } END_IF_FIELD } @@ -282,13 +307,25 @@ static bool mc_FLE2RangeFindSpecEdgesInfo_parse(mc_FLE2RangeFindSpecEdgesInfo_t CHECK_HAS(indexMax) // Do not error if precision is not present. Precision optional and only // applies to double/decimal128. + + if (!use_range_v2 && out->trimFactor.set) { + CLIENT_ERR_PREFIXED("'trimFactor' is not supported for QE range v1"); + return false; + } + return true; fail: return false; } -bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status) { +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error parsing FLE2RangeFindSpec" + +bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, + const bson_iter_t *in, + bool use_range_v2, + mongocrypt_status_t *status) { BSON_ASSERT_PARAM(out); BSON_ASSERT_PARAM(in); @@ -298,7 +335,7 @@ bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, const bson_iter_t * *out = (mc_FLE2RangeFindSpec_t){{{{0}}}}; if (!BSON_ITER_HOLDS_DOCUMENT(&iter)) { - CLIENT_ERR("invalid FLE2RangeFindSpec: must be an iterator to a document"); + CLIENT_ERR_PREFIXED("must be an iterator to a document"); return false; } bson_iter_recurse(&iter, &iter); @@ -308,7 +345,7 @@ bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, const bson_iter_t * BSON_ASSERT(field); IF_FIELD(edgesInfo) { - if (!mc_FLE2RangeFindSpecEdgesInfo_parse(&out->edgesInfo.value, &iter, status)) { + if (!mc_FLE2RangeFindSpecEdgesInfo_parse(&out->edgesInfo.value, &iter, use_range_v2, status)) { goto fail; } out->edgesInfo.set = true; @@ -317,7 +354,7 @@ bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, const bson_iter_t * IF_FIELD(payloadId) { if (!BSON_ITER_HOLDS_INT32(&iter)) { - CLIENT_ERR("invalid FLE2RangeFindSpec: 'payloadId' must be an int32"); + CLIENT_ERR_PREFIXED("'payloadId' must be an int32"); goto fail; } out->payloadId = bson_iter_int32(&iter); @@ -326,15 +363,14 @@ bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, const bson_iter_t * IF_FIELD(firstOperator) { if (!BSON_ITER_HOLDS_INT32(&iter)) { - CLIENT_ERR("invalid FLE2RangeFindSpec: 'firstOperator' must be an int32"); + CLIENT_ERR_PREFIXED("'firstOperator' must be an int32"); goto fail; } const int32_t first_op = bson_iter_int32(&iter); if (first_op < FLE2RangeOperator_min_val || first_op > FLE2RangeOperator_max_val) { - CLIENT_ERR("invalid FLE2RangeFindSpec: 'firstOperator' must be " - "between %d and %d", - FLE2RangeOperator_min_val, - FLE2RangeOperator_max_val); + CLIENT_ERR_PREFIXED("'firstOperator' must be between %d and %d", + FLE2RangeOperator_min_val, + FLE2RangeOperator_max_val); goto fail; } out->firstOperator = (mc_FLE2RangeOperator_t)first_op; @@ -343,15 +379,14 @@ bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, const bson_iter_t * IF_FIELD(secondOperator) { if (!BSON_ITER_HOLDS_INT32(&iter)) { - CLIENT_ERR("invalid FLE2RangeFindSpec: 'secondOperator' must be an int32"); + CLIENT_ERR_PREFIXED("'secondOperator' must be an int32"); goto fail; } const int32_t second_op = bson_iter_int32(&iter); if (second_op < FLE2RangeOperator_min_val || second_op > FLE2RangeOperator_max_val) { - CLIENT_ERR("invalid FLE2RangeFindSpec: 'secondOperator' must be " - "between %d and %d", - FLE2RangeOperator_min_val, - FLE2RangeOperator_max_val); + CLIENT_ERR_PREFIXED("'secondOperator' must be between %d and %d", + FLE2RangeOperator_min_val, + FLE2RangeOperator_max_val); goto fail; } out->secondOperator = (mc_FLE2RangeOperator_t)second_op; @@ -369,17 +404,23 @@ bool mc_FLE2RangeFindSpec_parse(mc_FLE2RangeFindSpec_t *out, const bson_iter_t * return false; } -bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, const bson_iter_t *in, mongocrypt_status_t *status) { +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error parsing FLE2RangeInsertSpec" + +bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, + const bson_iter_t *in, + bool use_range_v2, + mongocrypt_status_t *status) { BSON_ASSERT_PARAM(out); BSON_ASSERT_PARAM(in); *out = (mc_FLE2RangeInsertSpec_t){{0}}; bson_iter_t iter = *in; - bool has_v = false, has_min = false, has_max = false, has_precision = false; + bool has_v = false, has_min = false, has_max = false, has_precision = false, has_trimFactor = false; if (!BSON_ITER_HOLDS_DOCUMENT(&iter)) { - CLIENT_ERR("invalid FLE2RangeInsertSpec: must be an iterator to a document"); + CLIENT_ERR_PREFIXED("must be an iterator to a document"); return false; } bson_iter_recurse(&iter, &iter); @@ -405,17 +446,29 @@ bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, const bson_iter IF_FIELD(precision) { if (!BSON_ITER_HOLDS_INT32(&iter)) { - CLIENT_ERR("invalid FLE2RangeFindSpecEdgesInfo: 'precision' must " - "be an int32"); + CLIENT_ERR_PREFIXED("'precision' must be an int32"); goto fail; } int32_t val = bson_iter_int32(&iter); if (val < 0) { - CLIENT_ERR("invalid FLE2RangeFindSpecEdgesInfo: 'precision' must be" - "non-negative"); + CLIENT_ERR_PREFIXED("'precision' must be non-negative"); goto fail; } - out->precision = OPT_U32((uint32_t)val); + out->precision = OPT_I32(val); + } + END_IF_FIELD + + IF_FIELD(trimFactor) { + if (!BSON_ITER_HOLDS_INT32(&iter)) { + CLIENT_ERR_PREFIXED("'trimFactor' must be an int32"); + goto fail; + } + int32_t val = bson_iter_int32(&iter); + if (val < 0) { + CLIENT_ERR_PREFIXED("'trimFactor' must be non-negative"); + goto fail; + } + out->trimFactor = OPT_I32(val); } END_IF_FIELD } @@ -425,8 +478,16 @@ bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out, const bson_iter CHECK_HAS(max) // Do not error if precision is not present. Precision optional and only // applies to double/decimal128. + + if (!use_range_v2 && out->trimFactor.set) { + CLIENT_ERR_PREFIXED("'trimFactor' is not supported for QE range v1"); + return false; + } + return true; fail: return false; } + +#undef ERROR_PREFIX diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private-v2.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private-v2.h index 452f2a9..02fa0e5 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private-v2.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private-v2.h @@ -25,7 +25,7 @@ typedef struct { _mongocrypt_buffer_t edcDerivedToken; // d _mongocrypt_buffer_t escDerivedToken; // s _mongocrypt_buffer_t serverDerivedFromDataToken; // l - int64_t maxContentionCounter; // cm + int64_t maxContentionFactor; // cm } mc_FLE2FindEqualityPayloadV2_t; void mc_FLE2FindEqualityPayloadV2_init(mc_FLE2FindEqualityPayloadV2_t *payload); diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private.h index 8eb399e..6dcc0e3 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private.h @@ -26,7 +26,7 @@ typedef struct { _mongocrypt_buffer_t escDerivedToken; // s _mongocrypt_buffer_t eccDerivedToken; // c _mongocrypt_buffer_t serverEncryptionToken; // e - int64_t maxContentionCounter; // cm + int64_t maxContentionFactor; // cm } mc_FLE2FindEqualityPayload_t; void mc_FLE2FindEqualityPayload_init(mc_FLE2FindEqualityPayload_t *payload); diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-v2.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-v2.c index 02d2dbf..afd1654 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-v2.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-v2.c @@ -99,7 +99,7 @@ bool mc_FLE2FindEqualityPayloadV2_parse(mc_FLE2FindEqualityPayloadV2_t *out, CLIENT_ERR("Field 'cm' expected to hold an int64"); goto fail; } - out->maxContentionCounter = bson_iter_int64(&iter); + out->maxContentionFactor = bson_iter_int64(&iter); } END_IF_FIELD } @@ -126,7 +126,7 @@ bool mc_FLE2FindEqualityPayloadV2_serialize(const mc_FLE2FindEqualityPayloadV2_t APPEND_BINDATA("d", payload->edcDerivedToken); APPEND_BINDATA("s", payload->escDerivedToken); APPEND_BINDATA("l", payload->serverDerivedFromDataToken); - if (!BSON_APPEND_INT64(out, "cm", payload->maxContentionCounter)) { + if (!BSON_APPEND_INT64(out, "cm", payload->maxContentionFactor)) { return false; } return true; diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload.c index 24d551a..e60dfa9 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload.c @@ -101,7 +101,7 @@ bool mc_FLE2FindEqualityPayload_parse(mc_FLE2FindEqualityPayload_t *out, CLIENT_ERR("Field 'cm' expected to hold an int64"); goto fail; } - out->maxContentionCounter = bson_iter_int64(&iter); + out->maxContentionFactor = bson_iter_int64(&iter); } END_IF_FIELD } @@ -130,7 +130,7 @@ bool mc_FLE2FindEqualityPayload_serialize(const mc_FLE2FindEqualityPayload_t *pa PAYLOAD_APPEND_BINDATA("s", payload->escDerivedToken); PAYLOAD_APPEND_BINDATA("c", payload->eccDerivedToken); PAYLOAD_APPEND_BINDATA("e", payload->serverEncryptionToken); - if (!BSON_APPEND_INT64(out, "cm", payload->maxContentionCounter)) { + if (!BSON_APPEND_INT64(out, "cm", payload->maxContentionFactor)) { return false; } return true; diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h index f35331a..c5ed226 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h @@ -23,13 +23,14 @@ #include "mc-array-private.h" #include "mc-fle2-range-operator-private.h" +#include "mc-optional-private.h" /** FLE2FindRangePayloadEdgesInfoV2 represents the token information for a range * find query. It is encoded inside an FLE2FindRangePayloadV2. */ typedef struct { mc_array_t edgeFindTokenSetArray; // g - int64_t maxContentionCounter; // cm + int64_t maxContentionFactor; // cm } mc_FLE2FindRangePayloadEdgesInfoV2_t; /** @@ -44,8 +45,17 @@ typedef struct { * } FLE2FindRangePayloadV2; * * bson is a BSON document of this form: - * g: array // Array of Edges - * cm: // Queryable Encryption max counter + * payload: + * g: array // Array of Edges + * cm: // Queryable Encryption max counter + * payloadId: // Payload ID. + * firstOperator: + * secondOperator: + * sp: optional // Sparsity. + * pn: optional // Precision. + * tf: optional // Trim Factor. + * mn: optional // Index Min. + * mx: optional // Index Max. */ typedef struct { struct { @@ -61,12 +71,17 @@ typedef struct { // secondOperator represents the second query operator for which this payload // was generated. Only populated for two-sided ranges. It is 0 if unset. mc_FLE2RangeOperator_t secondOperator; + mc_optional_int64_t sparsity; // sp + mc_optional_int32_t precision; // pn + mc_optional_int32_t trimFactor; // tf + bson_value_t indexMin; // mn + bson_value_t indexMax; // mx } mc_FLE2FindRangePayloadV2_t; /** * EdgeFindTokenSetV2 is the following BSON document: - * d: // EDCDerivedFromDataTokenAndCounter - * s: // ESCDerivedFromDataTokenAndCounter + * d: // EDCDerivedFromDataTokenAndContentionFactor + * s: // ESCDerivedFromDataTokenAndContentionFactor * l: // ServerDerivedFromDataToken * * Instances of mc_EdgeFindTokenSetV2_t are expected to be owned by @@ -81,7 +96,7 @@ typedef struct { void mc_FLE2FindRangePayloadV2_init(mc_FLE2FindRangePayloadV2_t *payload); -bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payload, bson_t *out); +bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payload, bson_t *out, bool use_range_v2); void mc_FLE2FindRangePayloadV2_cleanup(mc_FLE2FindRangePayloadV2_t *payload); diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private.h index 0796c30..d2e4ee4 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private.h @@ -32,7 +32,7 @@ typedef struct { mc_array_t edgeFindTokenSetArray; // g _mongocrypt_buffer_t serverEncryptionToken; // e - int64_t maxContentionCounter; // cm + int64_t maxContentionFactor; // cm } mc_FLE2FindRangePayloadEdgesInfo_t; /** @@ -49,7 +49,7 @@ typedef struct { * bson is a BSON document of this form: * g: array // Array of Edges * e: // ServerDataEncryptionLevel1Token - * cm: // Queryable Encryption max counter + * cm: // Queryable Encryption max contentionFactor */ typedef struct { struct { @@ -69,9 +69,9 @@ typedef struct { /** * EdgeFindTokenSet is the following BSON document: - * d: // EDCDerivedFromDataTokenAndCounter - * s: // ESCDerivedFromDataTokenAndCounter - * c: // ECCDerivedFromDataTokenAndCounter + * d: // EDCDerivedFromDataTokenAndContentionFactor + * s: // ESCDerivedFromDataTokenAndContentionFactor + * c: // ECCDerivedFromDataTokenAndContentionFactor * * Instances of mc_EdgeFindTokenSet_t are expected to be owned by * mc_FLE2FindRangePayload_t and are freed in diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-v2.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-v2.c index dfb5421..e07cd76 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-v2.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-v2.c @@ -53,7 +53,7 @@ void mc_FLE2FindRangePayloadV2_cleanup(mc_FLE2FindRangePayloadV2_t *payload) { return false; \ } -bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payload, bson_t *out) { +bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payload, bson_t *out, bool use_range_v2) { BSON_ASSERT_PARAM(out); BSON_ASSERT_PARAM(payload); @@ -106,7 +106,7 @@ bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payl } // Append "payload.cm". - if (!BSON_APPEND_INT64(&payload_bson, "cm", payload->payload.value.maxContentionCounter)) { + if (!BSON_APPEND_INT64(&payload_bson, "cm", payload->payload.value.maxContentionFactor)) { return false; } @@ -131,6 +131,42 @@ bool mc_FLE2FindRangePayloadV2_serialize(const mc_FLE2FindRangePayloadV2_t *payl return false; } + if (use_range_v2) { + // Encode parameters that were used to generate the mincover. + // The crypto parameters are all optionally set. Find payloads may come in pairs (a lower and upper bound). + // One of the pair includes the mincover. The other payload was not generated with crypto parameters. + + if (payload->sparsity.set) { + if (!BSON_APPEND_INT64(out, "sp", payload->sparsity.value)) { + return false; + } + } + + if (payload->precision.set) { + if (!BSON_APPEND_INT32(out, "pn", payload->precision.value)) { + return false; + } + } + + if (payload->trimFactor.set) { + if (!BSON_APPEND_INT32(out, "tf", payload->trimFactor.value)) { + return false; + } + } + + if (payload->indexMin.value_type != BSON_TYPE_EOD) { + if (!BSON_APPEND_VALUE(out, "mn", &payload->indexMin)) { + return false; + } + } + + if (payload->indexMax.value_type != BSON_TYPE_EOD) { + if (!BSON_APPEND_VALUE(out, "mx", &payload->indexMax)) { + return false; + } + } + } + return true; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload.c index 4eb1de4..1a3610e 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload.c @@ -108,7 +108,7 @@ bool mc_FLE2FindRangePayload_serialize(const mc_FLE2FindRangePayload_t *payload, // Append "payload.e" and "payload.cm". APPEND_BINDATA(&payload_bson, "e", payload->payload.value.serverEncryptionToken); - if (!BSON_APPEND_INT64(&payload_bson, "cm", payload->payload.value.maxContentionCounter)) { + if (!BSON_APPEND_INT64(&payload_bson, "cm", payload->payload.value.maxContentionFactor)) { return false; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h index e355626..2ed4b32 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h @@ -20,6 +20,7 @@ #include #include "mc-array-private.h" +#include "mc-optional-private.h" #include "mongocrypt-buffer-private.h" #include "mongocrypt-private.h" #include "mongocrypt.h" @@ -36,8 +37,8 @@ * } FLE2InsertUpdatePayloadV2; * * bson is a BSON document of this form: - * d: // EDCDerivedFromDataTokenAndCounter - * s: // ESCDerivedFromDataTokenAndCounter + * d: // EDCDerivedFromDataTokenAndContentionFactor + * s: // ESCDerivedFromDataTokenAndContentionFactor * p: // Encrypted Tokens * u: // Index KeyId * t: // Encrypted type @@ -45,13 +46,18 @@ * e: // ServerDataEncryptionLevel1Token * l: // ServerDerivedFromDataToken * k: // Randomly sampled contention factor value - * g: array // Array of Edges + * g: array // Array of Edges. Only included for range payloads. + * sp: optional // Sparsity. Only included for range payloads. + * pn: optional // Precision. Only included for range payloads. + * tf: optional // Trim Factor. Only included for range payloads. + * mn: optional // Index Min. Only included for range payloads. + * mx: optional // Index Max. Only included for range payloads. * * p is the result of: * Encrypt( * key=ECOCToken, * plaintext=( - * ESCDerivedFromDataTokenAndCounter) + * ESCDerivedFromDataTokenAndContentionFactor) * ) * * v is the result of: @@ -72,14 +78,19 @@ typedef struct { _mongocrypt_buffer_t serverDerivedFromDataToken; // l int64_t contentionFactor; // k mc_array_t edgeTokenSetArray; // g + mc_optional_int64_t sparsity; // sp + mc_optional_int32_t precision; // pn + mc_optional_int32_t trimFactor; // tf + bson_value_t indexMin; // mn + bson_value_t indexMax; // mx _mongocrypt_buffer_t plaintext; _mongocrypt_buffer_t userKeyId; } mc_FLE2InsertUpdatePayloadV2_t; /** * EdgeTokenSetV2 is the following BSON document: - * d: // EDCDerivedFromDataTokenAndCounter - * s: // ESCDerivedFromDataTokenAndCounter + * d: // EDCDerivedFromDataTokenAndContentionFactor + * s: // ESCDerivedFromDataTokenAndContentionFactor * l: // ServerDerivedFromDataToken * p: // Encrypted Tokens * @@ -110,7 +121,9 @@ const _mongocrypt_buffer_t *mc_FLE2InsertUpdatePayloadV2_decrypt(_mongocrypt_cry bool mc_FLE2InsertUpdatePayloadV2_serialize(const mc_FLE2InsertUpdatePayloadV2_t *payload, bson_t *out); -bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePayloadV2_t *payload, bson_t *out); +bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePayloadV2_t *payload, + bson_t *out, + bool use_range_v2); void mc_FLE2InsertUpdatePayloadV2_cleanup(mc_FLE2InsertUpdatePayloadV2_t *payload); diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private.h index 76bdf4a..a7d4495 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private.h @@ -36,9 +36,9 @@ * } FLE2InsertUpdatePayload; * * bson is a BSON document of this form: - * d: // EDCDerivedFromDataTokenAndCounter - * s: // ESCDerivedFromDataTokenAndCounter - * c: // ECCDerivedFromDataTokenAndCounter + * d: // EDCDerivedFromDataTokenAndContentionFactor + * s: // ESCDerivedFromDataTokenAndContentionFactor + * c: // ECCDerivedFromDataTokenAndContentionFactor * p: // Encrypted Tokens * u: // Index KeyId * t: // Encrypted type @@ -50,8 +50,8 @@ * Encrypt( * key=ECOCToken, * plaintext=( - * ESCDerivedFromDataTokenAndCounter || - * ECCDerivedFromDataTokenAndCounter) + * ESCDerivedFromDataTokenAndContentionFactor || + * ECCDerivedFromDataTokenAndContentionFactor) * ) * * v is the result of: @@ -77,9 +77,9 @@ typedef struct { /** * EdgeTokenSet is the following BSON document: - * d: // EDCDerivedFromDataTokenAndCounter - * s: // ESCDerivedFromDataTokenAndCounter - * c: // ECCDerivedFromDataTokenAndCounter + * d: // EDCDerivedFromDataTokenAndContentionFactor + * s: // ESCDerivedFromDataTokenAndContentionFactor + * c: // ECCDerivedFromDataTokenAndContentionFactor * p: // Encrypted Tokens * * Instances of mc_EdgeTokenSet_t are expected to be owned by diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-v2.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-v2.c index f4e9bf3..b86e412 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-v2.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-v2.c @@ -18,6 +18,7 @@ #include "mc-fle2-insert-update-payload-private-v2.h" #include "mongocrypt-buffer-private.h" +#include "mongocrypt-util-private.h" // mc_bson_type_to_string #include "mongocrypt.h" void mc_FLE2InsertUpdatePayloadV2_init(mc_FLE2InsertUpdatePayloadV2_t *payload) { @@ -53,6 +54,8 @@ void mc_FLE2InsertUpdatePayloadV2_cleanup(mc_FLE2InsertUpdatePayloadV2_t *payloa mc_EdgeTokenSetV2_cleanup(&entry); } _mc_array_destroy(&payload->edgeTokenSetArray); + bson_value_destroy(&payload->indexMin); + bson_value_destroy(&payload->indexMax); } #define IF_FIELD(Name) \ @@ -104,6 +107,7 @@ bool mc_FLE2InsertUpdatePayloadV2_parse(mc_FLE2InsertUpdatePayloadV2_t *out, bool has_d = false, has_s = false, has_p = false; bool has_u = false, has_t = false, has_v = false; bool has_e = false, has_l = false, has_k = false; + bool has_sp = false, has_pn = false, has_tf = false, has_mn = false, has_mx = false; bson_t in_bson; BSON_ASSERT_PARAM(out); @@ -163,6 +167,57 @@ bool mc_FLE2InsertUpdatePayloadV2_parse(mc_FLE2InsertUpdatePayloadV2_t *out, PARSE_BINARY(v, value) PARSE_BINARY(e, serverEncryptionToken) PARSE_BINARY(l, serverDerivedFromDataToken) + + IF_FIELD(sp) { + if (!BSON_ITER_HOLDS_INT64(&iter)) { + CLIENT_ERR("Field 'sp' expected to hold an int64, got: %s", + mc_bson_type_to_string(bson_iter_type(&iter))); + goto fail; + } + int64_t sparsity = bson_iter_int64(&iter); + out->sparsity = OPT_I64(sparsity); + } + END_IF_FIELD + + IF_FIELD(pn) { + if (!BSON_ITER_HOLDS_INT32(&iter)) { + CLIENT_ERR("Field 'pn' expected to hold an int32, got: %s", + mc_bson_type_to_string(bson_iter_type(&iter))); + goto fail; + } + int32_t precision = bson_iter_int32(&iter); + if (precision < 0) { + CLIENT_ERR("Field 'pn' must be non-negative, got: %" PRId32, precision); + goto fail; + } + out->precision = OPT_I32(precision); + } + END_IF_FIELD + + IF_FIELD(tf) { + if (!BSON_ITER_HOLDS_INT32(&iter)) { + CLIENT_ERR("Field 'tf' expected to hold an int32, got: %s", + mc_bson_type_to_string(bson_iter_type(&iter))); + goto fail; + } + int32_t trimFactor = bson_iter_int32(&iter); + if (trimFactor < 0) { + CLIENT_ERR("Field 'tf' must be non-negative, got: %" PRId32, trimFactor); + goto fail; + } + out->trimFactor = OPT_I32(trimFactor); + } + END_IF_FIELD + + IF_FIELD(mn) { + bson_value_copy(bson_iter_value(&iter), &out->indexMin); + } + END_IF_FIELD + + IF_FIELD(mx) { + bson_value_copy(bson_iter_value(&iter), &out->indexMax); + } + END_IF_FIELD } CHECK_HAS(d); @@ -174,6 +229,7 @@ bool mc_FLE2InsertUpdatePayloadV2_parse(mc_FLE2InsertUpdatePayloadV2_t *out, CHECK_HAS(e); CHECK_HAS(l); CHECK_HAS(k); + // The fields `sp`, `pn`, `tf`, `mn`, and `mx` are only set for "range" payloads. if (!_mongocrypt_buffer_from_subrange(&out->userKeyId, &out->value, 0, UUID_LEN)) { CLIENT_ERR("failed to create userKeyId buffer"); @@ -213,7 +269,9 @@ bool mc_FLE2InsertUpdatePayloadV2_serialize(const mc_FLE2InsertUpdatePayloadV2_t return true; } -bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePayloadV2_t *payload, bson_t *out) { +bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePayloadV2_t *payload, + bson_t *out, + bool use_range_v2) { BSON_ASSERT_PARAM(out); BSON_ASSERT_PARAM(payload); @@ -257,6 +315,36 @@ bool mc_FLE2InsertUpdatePayloadV2_serializeForRange(const mc_FLE2InsertUpdatePay return false; } + if (use_range_v2) { + // Encode parameters that were used to generate the payload. + BSON_ASSERT(payload->sparsity.set); + if (!BSON_APPEND_INT64(out, "sp", payload->sparsity.value)) { + return false; + } + + // Precision may be unset. + if (payload->precision.set) { + if (!BSON_APPEND_INT32(out, "pn", payload->precision.value)) { + return false; + } + } + + BSON_ASSERT(payload->trimFactor.set); + if (!BSON_APPEND_INT32(out, "tf", payload->trimFactor.value)) { + return false; + } + + BSON_ASSERT(payload->indexMin.value_type != BSON_TYPE_EOD); + if (!BSON_APPEND_VALUE(out, "mn", &payload->indexMin)) { + return false; + } + + BSON_ASSERT(payload->indexMax.value_type != BSON_TYPE_EOD); + if (!BSON_APPEND_VALUE(out, "mx", &payload->indexMax)) { + return false; + } + } + return true; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c index 47f8b07..32d8687 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c @@ -180,7 +180,7 @@ bool mc_FLE2IndexedEncryptedValueV2_add_S_Key(_mongocrypt_crypto_t *crypto, CLIENT_ERR("Invalid ServerEncryptedValue length, got %" PRIu32 ", expected more than %d", DecryptedServerEncryptedValueLen, UUID_LEN); - return false; + goto fail; } _mongocrypt_buffer_resize(&iev->DecryptedServerEncryptedValue, DecryptedServerEncryptedValueLen); uint32_t bytes_written = 0; @@ -196,7 +196,7 @@ bool mc_FLE2IndexedEncryptedValueV2_add_S_Key(_mongocrypt_crypto_t *crypto, BSON_ASSERT(bytes_written == DecryptedServerEncryptedValueLen); if (!_mongocrypt_buffer_from_subrange(&iev->K_KeyId, &iev->DecryptedServerEncryptedValue, 0, UUID_LEN)) { CLIENT_ERR("Error creating K_KeyId subrange from DecryptedServerEncryptedValue"); - return false; + goto fail; } iev->K_KeyId.subtype = BSON_SUBTYPE_UUID; @@ -207,7 +207,7 @@ bool mc_FLE2IndexedEncryptedValueV2_add_S_Key(_mongocrypt_crypto_t *crypto, iev->DecryptedServerEncryptedValue.len - UUID_LEN)) { CLIENT_ERR("Error creating ClientEncryptedValue subrange from " "DecryptedServerEncryptedValue"); - return false; + goto fail; } iev->ClientEncryptedValueDecoded = true; diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev.c index cc9f4a1..0d2654d 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev.c @@ -100,7 +100,6 @@ bool mc_FLE2IndexedEncryptedValue_write(_mongocrypt_crypto_t *crypto, goto cleanup; \ } - const _mongocrypt_value_encryption_algorithm_t *fle2alg = _mcFLE2Algorithm(); bool ok = false; BSON_ASSERT_PARAM(crypto); @@ -130,27 +129,6 @@ bool mc_FLE2IndexedEncryptedValue_write(_mongocrypt_crypto_t *crypto, index_tokens, &encryption_out, status)); - uint32_t expected_plaintext_size = 0; - CHECK_AND_GOTO(safe_uint32_t_sum(ClientEncryptedValue->len, - (uint32_t)(sizeof(uint64_t) * 2 + sizeof(uint32_t) * 3), - &expected_plaintext_size, - status)); - - uint32_t expected_cipher_size = fle2alg->get_ciphertext_len(expected_plaintext_size, status); - - if (expected_cipher_size == 0) { - CHECK_AND_GOTO(false); - } - - uint32_t expected_buf_size = 0; - CHECK_AND_RETURN( - safe_uint32_t_sum(expected_cipher_size, (uint32_t)(1 + sizeof(S_KeyId)), &expected_buf_size, status)); - - if (buf->len < expected_buf_size) { - CLIENT_ERR("mc_FLE2IndexedEncryptedValue_write buf is not large enough for iev"); - CHECK_AND_GOTO(false); - } - mc_writer_t writer; mc_writer_init_from_buffer(&writer, buf, __FUNCTION__); @@ -207,7 +185,7 @@ static bool mc_fle2IndexedEncryptedValue_encrypt(_mongocrypt_crypto_t *crypto, uint32_t ciphertext_len = fle2alg->get_ciphertext_len(expected_buf_size, status); if (ciphertext_len == 0) { - return false; + goto cleanup; } _mongocrypt_buffer_resize(out, ciphertext_len); diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds-private.h index 3d99c6b..d89827c 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds-private.h @@ -52,7 +52,7 @@ bool mc_FLE2RangeFindDriverSpec_parse(mc_FLE2RangeFindDriverSpec_t *spec, // `out` must be initialized by caller. bool mc_FLE2RangeFindDriverSpec_to_placeholders(mc_FLE2RangeFindDriverSpec_t *spec, const mc_RangeOpts_t *range_opts, - int64_t maxContentionCounter, + int64_t maxContentionFactor, const _mongocrypt_buffer_t *user_key_id, const _mongocrypt_buffer_t *index_key_id, int32_t payloadId, @@ -73,9 +73,10 @@ typedef struct { mc_FLE2RangeOperator_t secondOp; bson_iter_t indexMin; bson_iter_t indexMax; - int64_t maxContentionCounter; + int64_t maxContentionFactor; int64_t sparsity; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_makeRangeFindPlaceholder_args_t; // mc_makeRangeFindPlaceholder creates a placeholder to be consumed by diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds.c b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds.c index 02dac30..0622bfd 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds.c @@ -70,7 +70,7 @@ static bool parse_and(const bson_t *in, bson_iter_t *out, mongocrypt_status_t *s BSON_ASSERT_PARAM(out); BSON_ASSERT(status || true); - bson_iter_t and; + bson_iter_t and = {0}; if (!bson_iter_init(&and, in) || !bson_iter_next(&and) || 0 != strcmp(bson_iter_key(&and), "$and")) { ERR_WITH_BSON(in, "%s", "error unable to find '$and'"); return false; @@ -105,7 +105,7 @@ parse_aggregate_expression(const bson_t *orig, bson_iter_t *in, operator_value_t BSON_ASSERT_PARAM(out); BSON_ASSERT(status || true); - bson_iter_t array, value; + bson_iter_t array = {0}, value; const char *op_type_str = bson_iter_key(in); bool ok = false; const char *field; @@ -162,7 +162,7 @@ parse_match_expression(const bson_t *orig, bson_iter_t *in, operator_value_t *ou BSON_ASSERT_PARAM(out); BSON_ASSERT(status || true); - bson_iter_t document, value; + bson_iter_t document = {0}, value; const char *op_type_str; bool ok = false; const char *field = bson_iter_key(in); @@ -217,7 +217,7 @@ bool mc_FLE2RangeFindDriverSpec_parse(mc_FLE2RangeFindDriverSpec_t *spec, // {$and: [{$gt: ["$age", 5]}, {$lt:["$age", 50]}]} // Or `in` may be a Match Expression with this form: // {$and: [{age: {$gt: 5}}, {age: {$lt: 50}} ]} - bson_iter_t and, array; + bson_iter_t and = {0}, array = {0}; bool ok = false; if (!parse_and(in, &and, status)) { @@ -264,7 +264,7 @@ bool mc_FLE2RangeFindDriverSpec_parse(mc_FLE2RangeFindDriverSpec_t *spec, } } - operator_value_t op; + operator_value_t op = {0}; switch (arg_type) { case AGGREGATE_EXPRESSION: if (!parse_aggregate_expression(in, &doc, &op, status)) { @@ -364,8 +364,10 @@ bool mc_makeRangeFindPlaceholder(mc_makeRangeFindPlaceholder_args_t *args, TRY(bson_append_iter(edgesInfo, "indexMin", -1, &args->indexMin)); TRY(bson_append_iter(edgesInfo, "indexMax", -1, &args->indexMax)); if (args->precision.set) { - BSON_ASSERT(args->precision.value <= INT32_MAX); - TRY(BSON_APPEND_INT32(edgesInfo, "precision", (int32_t)args->precision.value)); + TRY(BSON_APPEND_INT32(edgesInfo, "precision", args->precision.value)); + } + if (args->trimFactor.set) { + TRY(BSON_APPEND_INT32(edgesInfo, "trimFactor", args->trimFactor.value)); } TRY(BSON_APPEND_DOCUMENT(v, "edgesInfo", edgesInfo)); } @@ -383,7 +385,7 @@ bool mc_makeRangeFindPlaceholder(mc_makeRangeFindPlaceholder_args_t *args, TRY(_mongocrypt_buffer_append(args->index_key_id, p, "ki", 2)); TRY(_mongocrypt_buffer_append(args->user_key_id, p, "ku", 2)); TRY(BSON_APPEND_DOCUMENT(p, "v", v)); - TRY(BSON_APPEND_INT64(p, "cm", args->maxContentionCounter)); + TRY(BSON_APPEND_INT64(p, "cm", args->maxContentionFactor)); TRY(BSON_APPEND_INT64(p, "s", args->sparsity)); #undef TRY @@ -403,7 +405,7 @@ bool mc_makeRangeFindPlaceholder(mc_makeRangeFindPlaceholder_args_t *args, bool mc_FLE2RangeFindDriverSpec_to_placeholders(mc_FLE2RangeFindDriverSpec_t *spec, const mc_RangeOpts_t *range_opts, - int64_t maxContentionCounter, + int64_t maxContentionFactor, const _mongocrypt_buffer_t *user_key_id, const _mongocrypt_buffer_t *index_key_id, int32_t payloadId, @@ -469,8 +471,9 @@ bool mc_FLE2RangeFindDriverSpec_to_placeholders(mc_FLE2RangeFindDriverSpec_t *sp .indexMin = indexMin, .indexMax = indexMax, .precision = range_opts->precision, - .maxContentionCounter = maxContentionCounter, - .sparsity = range_opts->sparsity}; + .maxContentionFactor = maxContentionFactor, + .sparsity = range_opts->sparsity, + .trimFactor = range_opts->trimFactor}; // First operator is the non-stub. if (!mc_makeRangeFindPlaceholder(&args, &p1, status)) { @@ -485,7 +488,7 @@ bool mc_FLE2RangeFindDriverSpec_to_placeholders(mc_FLE2RangeFindDriverSpec_t *sp .payloadId = payloadId, .firstOp = spec->firstOp, .secondOp = spec->secondOp, - .maxContentionCounter = maxContentionCounter, + .maxContentionFactor = maxContentionFactor, .sparsity = range_opts->sparsity}; // First operator is the non-stub. diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-optional-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-optional-private.h index d27a53d..42a92eb 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-optional-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-optional-private.h @@ -23,6 +23,17 @@ #include "./mc-dec128.h" #include "./mlib/int128.h" +typedef struct { + bool set; + bool value; +} mc_optional_bool_t; + +#define OPT_BOOL(val) \ + (mc_optional_bool_t) { .set = true, .value = val } + +#define OPT_BOOL_C(val) \ + { .set = true, .value = val } + typedef struct { bool set; int32_t value; diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation-private.h index e9d2a5f..268eef3 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation-private.h @@ -37,49 +37,59 @@ size_t mc_edges_len(mc_edges_t *edges); // mc_edges_destroys frees `edges`. void mc_edges_destroy(mc_edges_t *edges); +// mc_edges_is_leaf returns whether the given edge is the leaf node of the edge set. +bool mc_edges_is_leaf(const mc_edges_t *edges, const char *edge); + +// Return the trimFactor that was used to generate these edges. +int32_t mc_edges_get_used_trimFactor(const mc_edges_t *edges); + typedef struct { int32_t value; mc_optional_int32_t min; mc_optional_int32_t max; size_t sparsity; + mc_optional_int32_t trimFactor; } mc_getEdgesInt32_args_t; // mc_getEdgesInt32 implements the Edge Generation algorithm described in // SERVER-67751 for int32_t. -mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t *status); +mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t *status, bool use_range_v2); typedef struct { int64_t value; mc_optional_int64_t min; mc_optional_int64_t max; size_t sparsity; + mc_optional_int32_t trimFactor; } mc_getEdgesInt64_args_t; // mc_getEdgesInt64 implements the Edge Generation algorithm described in // SERVER-67751 for int64_t. -mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t *status); +mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t *status, bool use_range_v2); typedef struct { double value; size_t sparsity; mc_optional_double_t min; mc_optional_double_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_getEdgesDouble_args_t; // mc_getEdgesDouble implements the Edge Generation algorithm described in // SERVER-67751 for double. -mc_edges_t *mc_getEdgesDouble(mc_getEdgesDouble_args_t args, mongocrypt_status_t *status); +mc_edges_t *mc_getEdgesDouble(mc_getEdgesDouble_args_t args, mongocrypt_status_t *status, bool use_range_v2); #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT typedef struct { mc_dec128 value; size_t sparsity; mc_optional_dec128_t min, max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_getEdgesDecimal128_args_t; -mc_edges_t *mc_getEdgesDecimal128(mc_getEdgesDecimal128_args_t args, mongocrypt_status_t *status); +mc_edges_t *mc_getEdgesDecimal128(mc_getEdgesDecimal128_args_t args, mongocrypt_status_t *status, bool use_range_v2); #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT BSON_STATIC_ASSERT2(ull_is_u64, sizeof(uint64_t) == sizeof(unsigned long long)); diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c b/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c index 3e7c5d0..10b266a 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "mc-optional-private.h" #include "mc-range-edge-generation-private.h" #include "mc-array-private.h" @@ -25,27 +26,60 @@ struct _mc_edges_t { size_t sparsity; /* edges is an array of `char*` edge strings. */ mc_array_t edges; + char *leaf; + int32_t usedTrimFactor; // The `trimFactor` that was used to produce these edges. }; -static mc_edges_t *mc_edges_new(const char *leaf, size_t sparsity, mongocrypt_status_t *status) { +int32_t mc_edges_get_used_trimFactor(const mc_edges_t *edges) { + return edges->usedTrimFactor; +} + +static mc_edges_t *mc_edges_new(const char *leaf, + size_t sparsity, + mc_optional_int32_t opt_trimFactor, + mongocrypt_status_t *status, + bool use_range_v2) { BSON_ASSERT_PARAM(leaf); if (sparsity < 1) { CLIENT_ERR("sparsity must be 1 or larger"); return NULL; } + + const size_t leaf_len = strlen(leaf); + const int32_t trimFactor = trimFactorDefault(leaf_len, opt_trimFactor, use_range_v2); + if (trimFactor != 0 && bson_cmp_greater_equal_su(trimFactor, leaf_len)) { + // We append a total of leaf_len + 1 (for the root) - trimFactor edges. When this number is equal to 1, we + // degenerate into equality, which is not desired, so trimFactor must be less than leaf_len. + CLIENT_ERR("trimFactor must be less than the number of bits (%ld) used to represent an element of the domain, " + "but got %" PRId32, + leaf_len, + trimFactor); + return NULL; + } + if (trimFactor < 0) { + CLIENT_ERR("trimFactor must be >= 0, but got %" PRId32, trimFactor); + return NULL; + } + mc_edges_t *edges = bson_malloc0(sizeof(mc_edges_t)); + edges->usedTrimFactor = trimFactor; edges->sparsity = sparsity; _mc_array_init(&edges->edges, sizeof(char *)); + edges->leaf = bson_strdup(leaf); - char *root = bson_strdup("root"); - _mc_array_append_val(&edges->edges, root); + if (trimFactor == 0) { + char *root = bson_strdup("root"); + _mc_array_append_val(&edges->edges, root); + } char *leaf_copy = bson_strdup(leaf); _mc_array_append_val(&edges->edges, leaf_copy); - const size_t leaf_len = strlen(leaf); - // Start loop at 1. The full leaf is unconditionally appended after loop. - for (size_t i = 1; i < leaf_len; i++) { + // Start loop at max(trimFactor, 1). The full leaf is unconditionally appended after loop. + BSON_ASSERT(bson_in_range_size_t_signed(trimFactor)); + size_t trimFactor_sz = (size_t)trimFactor; + size_t startLevel = trimFactor > 0 ? trimFactor_sz : 1; + for (size_t i = startLevel; i < leaf_len; i++) { if (i % sparsity == 0) { char *edge = bson_malloc(i + 1); bson_strncpy(edge, leaf, i + 1); @@ -78,20 +112,26 @@ void mc_edges_destroy(mc_edges_t *edges) { bson_free(val); } _mc_array_destroy(&edges->edges); + bson_free(edges->leaf); bson_free(edges); } +bool mc_edges_is_leaf(const mc_edges_t *edges, const char *edge) { + BSON_ASSERT_PARAM(edges); + BSON_ASSERT_PARAM(edge); + + return strcmp(edge, edges->leaf) == 0; +} + mc_bitstring mc_convert_to_bitstring_u64(uint64_t in) { mc_bitstring ret = {{0}}; char *out = ret.str; uint64_t bit = UINT64_C(1) << 63; + int loops = 0; // used to determine a bit shift while (bit > 0) { - if (bit & in) { - *out++ = '1'; - } else { - *out++ = '0'; - } + *out++ = (char)('0' + ((bit & in) >> (63 - loops))); bit >>= 1; + loops++; } return ret; } @@ -122,7 +162,7 @@ mc_bitstring mc_convert_to_bitstring_u128(mlib_int128 i) { return ret; } -mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t *status) { +mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t *status, bool use_range_v2) { mc_OSTType_Int32 got; if (!mc_getTypeInfo32((mc_getTypeInfo32_args_t){.value = args.value, .min = args.min, .max = args.max}, &got, @@ -138,11 +178,11 @@ mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t * mc_bitstring valueBin = mc_convert_to_bitstring_u32(got.value); size_t offset = mc_count_leading_zeros_u32(got.max); const char *leaf = valueBin.str + offset; - mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, status); + mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status, use_range_v2); return ret; } -mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t *status) { +mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t *status, bool use_range_v2) { mc_OSTType_Int64 got; if (!mc_getTypeInfo64((mc_getTypeInfo64_args_t){.value = args.value, .min = args.min, .max = args.max}, &got, @@ -158,18 +198,19 @@ mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t * mc_bitstring valueBin = mc_convert_to_bitstring_u64(got.value); size_t offset = mc_count_leading_zeros_u64(got.max); const char *leaf = valueBin.str + offset; - mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, status); + mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status, use_range_v2); return ret; } -mc_edges_t *mc_getEdgesDouble(mc_getEdgesDouble_args_t args, mongocrypt_status_t *status) { +mc_edges_t *mc_getEdgesDouble(mc_getEdgesDouble_args_t args, mongocrypt_status_t *status, bool use_range_v2) { mc_OSTType_Double got; if (!mc_getTypeInfoDouble((mc_getTypeInfoDouble_args_t){.value = args.value, .min = args.min, .max = args.max, .precision = args.precision}, &got, - status)) { + status, + use_range_v2)) { return NULL; } @@ -181,12 +222,12 @@ mc_edges_t *mc_getEdgesDouble(mc_getEdgesDouble_args_t args, mongocrypt_status_t mc_bitstring valueBin = mc_convert_to_bitstring_u64(got.value); size_t offset = mc_count_leading_zeros_u64(got.max); const char *leaf = valueBin.str + offset; - mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, status); + mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status, use_range_v2); return ret; } #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT -mc_edges_t *mc_getEdgesDecimal128(mc_getEdgesDecimal128_args_t args, mongocrypt_status_t *status) { +mc_edges_t *mc_getEdgesDecimal128(mc_getEdgesDecimal128_args_t args, mongocrypt_status_t *status, bool use_range_v2) { mc_OSTType_Decimal128 got; if (!mc_getTypeInfoDecimal128( (mc_getTypeInfoDecimal128_args_t){ @@ -196,7 +237,8 @@ mc_edges_t *mc_getEdgesDecimal128(mc_getEdgesDecimal128_args_t args, mongocrypt_ .precision = args.precision, }, &got, - status)) { + status, + use_range_v2)) { return NULL; } @@ -205,7 +247,7 @@ mc_edges_t *mc_getEdgesDecimal128(mc_getEdgesDecimal128_args_t args, mongocrypt_ mc_bitstring bits = mc_convert_to_bitstring_u128(got.value); size_t offset = mc_count_leading_zeros_u128(got.max); const char *leaf = bits.str + offset; - mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, status); + mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status, use_range_v2); return ret; } -#endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT \ No newline at end of file +#endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding-private.h index a79e97a..2250b1f 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding-private.h @@ -83,14 +83,22 @@ typedef struct { double value; mc_optional_double_t min; mc_optional_double_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; } mc_getTypeInfoDouble_args_t; +// `mc_canUsePrecisionModeDouble` returns true if the domain can be represented in fewer than 64 bits. +bool mc_canUsePrecisionModeDouble(double min, + double max, + int32_t precision, + uint32_t *maxBitsOut, + mongocrypt_status_t *status); + /* mc_getTypeInfoDouble encodes the double `args.value` into an OSTType_Double * `out`. Returns false and sets `status` on error. */ bool mc_getTypeInfoDouble(mc_getTypeInfoDouble_args_t args, mc_OSTType_Double *out, - mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT; + mongocrypt_status_t *status, + bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT; #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT /** @@ -103,9 +111,16 @@ typedef struct { typedef struct { mc_dec128 value; mc_optional_dec128_t min, max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; } mc_getTypeInfoDecimal128_args_t; +// `mc_canUsePrecisionModeDecimal` returns true if the domain can be represented in fewer than 128 bits. +bool mc_canUsePrecisionModeDecimal(mc_dec128 min, + mc_dec128 max, + int32_t precision, + uint32_t *maxBitsOut, + mongocrypt_status_t *status); + /** * @brief Obtain the OST encoding of a finite Decimal128 value. * @@ -116,7 +131,11 @@ typedef struct { */ bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args, mc_OSTType_Decimal128 *out, - mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT; + mongocrypt_status_t *status, + bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT; #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT +extern const int64_t mc_FLERangeSparsityDefault; + +int32_t trimFactorDefault(size_t maxlen, mc_optional_int32_t trimFactor, bool use_range_v2); #endif /* MC_RANGE_ENCODING_PRIVATE_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c b/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c index 65f3491..9c9ea27 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c @@ -162,8 +162,131 @@ bool mc_getTypeInfo64(mc_getTypeInfo64_args_t args, mc_OSTType_Int64 *out, mongo } #define exp10Double(x) pow(10, x) +#define SCALED_DOUBLE_BOUNDS 9007199254740992.0 // 2^53 + +uint64_t subtract_int64_t(int64_t max, int64_t min) { + BSON_ASSERT(max > min); + // If the values have the same sign, then simple subtraction + // will work because we know max > min. + if ((max > 0 && min > 0) || (max < 0 && min < 0)) { + return (uint64_t)(max - min); + } + + // If they are opposite signs, then we can just invert + // min to be positive and return the sum. + uint64_t u_return = (uint64_t)max; + u_return += (uint64_t)(~min + 1); + return u_return; +} + +bool ceil_log2_double(uint64_t i, uint32_t *maxBitsOut, mongocrypt_status_t *status) { + if (i == 0) { + CLIENT_ERR("Invalid input to ceil_log2_double function. Input cannot be 0."); + return false; + } + + uint32_t clz = (uint32_t)_mlibCountLeadingZeros_u64(i); + uint32_t bits; + if ((i & (i - 1)) == 0) { + bits = 64 - clz - 1; + } else { + bits = 64 - clz; + } + *maxBitsOut = bits; + return true; +} + +bool mc_canUsePrecisionModeDouble(double min, + double max, + int32_t precision, + uint32_t *maxBitsOut, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(maxBitsOut); + BSON_ASSERT(precision >= 0); + + if (min >= max) { + CLIENT_ERR("Invalid bounds for double range precision, min must be less than max. min: %g, max: %g", min, max); + return false; + } + + const double scaled_prc = exp10Double(precision); + + const double scaled_max = max * scaled_prc; + const double scaled_min = min * scaled_prc; + + if (scaled_max != trunc(scaled_max)) { + CLIENT_ERR("Invalid upper bound for double precision. Fractional digits must be less than the specified " + "precision value. max: %g", + max); + return false; + } + + if (scaled_min != trunc(scaled_min)) { + CLIENT_ERR("Invalid lower bound for double precision. Fractional digits must be less than the specified " + "precision value. min: %g", + min); + return false; + } + + if (fabs(scaled_max) >= SCALED_DOUBLE_BOUNDS) { + CLIENT_ERR( + "Invalid upper bound for double precision. Absolute scaled value of max must be less than %g. max: %g", + SCALED_DOUBLE_BOUNDS, + max); + return false; + } + + if (fabs(scaled_min) >= SCALED_DOUBLE_BOUNDS) { + CLIENT_ERR( + "Invalid lower bound for double precision. Absolute scaled value of min must be less than %g. min: %g", + SCALED_DOUBLE_BOUNDS, + min); + return false; + } + + const double t_1 = scaled_max - scaled_min; + const double t_4 = (double)UINT64_MAX - t_1; + const double t_5 = floor(log10(t_4)) - 1; + + if ((double)precision > t_5) { + CLIENT_ERR("Invalid value for precision. precision: %" PRId32, precision); + return false; + } + + const int64_t i_1 = (int64_t)(scaled_max); + const int64_t i_2 = (int64_t)(scaled_min); + + const uint64_t range = subtract_int64_t(i_1, i_2); + + if (((uint64_t)scaled_prc) > UINT64_MAX - range) { + CLIENT_ERR("Invalid value for min, max, and precision. The calculated domain size is too large. min: %g, max: " + "%g, precision: %" PRId32, + min, + max, + precision); + return false; + } + + const uint64_t i_3 = range + (uint64_t)(scaled_prc); -bool mc_getTypeInfoDouble(mc_getTypeInfoDouble_args_t args, mc_OSTType_Double *out, mongocrypt_status_t *status) { + if (!ceil_log2_double(i_3, maxBitsOut, status)) { + return false; + } + + // Integers between -2^53 and 2^53 can be exactly represented. Outside this range, doubles lose precision by a + // multiple of 2^(n-52) where n = #bits. We disallow users from using precision mode when the bounds exceed 2^53 to + // prevent the users from being surprised by how floating point math works. + if (*maxBitsOut >= 53) { + return false; + } + + return true; +} + +bool mc_getTypeInfoDouble(mc_getTypeInfoDouble_args_t args, + mc_OSTType_Double *out, + mongocrypt_status_t *status, + bool use_range_v2) { if (args.min.set != args.max.set || args.min.set != args.precision.set) { CLIENT_ERR("min, max, and precision must all be set or must all be unset"); return false; @@ -194,6 +317,19 @@ bool mc_getTypeInfoDouble(mc_getTypeInfoDouble_args_t args, mc_OSTType_Double *o } } + if (args.precision.set) { + if (args.precision.value < 0) { + CLIENT_ERR("Precision must be non-negative, but got %" PRId32, args.precision.value); + return false; + } + + double scaled = exp10Double(args.precision.value); + if (!mc_isfinite(scaled)) { + CLIENT_ERR("Precision is too large and cannot be used to calculate the scaled range bounds"); + return false; + } + } + const bool is_neg = args.value < 0.0; // Map negative 0 to zero so sign bit is 0. @@ -210,39 +346,33 @@ bool mc_getTypeInfoDouble(mc_getTypeInfoDouble_args_t args, mc_OSTType_Double *o bool use_precision_mode = false; uint32_t bits_range; if (args.precision.set) { - // Subnormal representations can support up to 5x10^-324 as a number - if (args.precision.value > 324) { - CLIENT_ERR("Precision must be between 0 and 324 inclusive, got: %" PRIu32, args.precision.value); - return false; - } - - double range = args.max.value - args.min.value; + use_precision_mode = + mc_canUsePrecisionModeDouble(args.min.value, args.max.value, args.precision.value, &bits_range, status); - // We can overflow if max = max double and min = min double so make sure - // we have finite number after we do subtraction - // Ignore conversion warnings to fix error with glibc. - if (mc_isfinite(range)) { - // This creates a range which is wider then we permit by our min/max - // bounds check with the +1 but it is as the algorithm is written in - // WRITING-11907. - double rangeAndPrecision = (range + 1) * exp10Double(args.precision.value); - - if (mc_isfinite(rangeAndPrecision)) { - double bits_range_double = log2(rangeAndPrecision); - bits_range = (uint32_t)ceil(bits_range_double); - - if (bits_range < 64) { - use_precision_mode = true; - } + if (!use_precision_mode && use_range_v2) { + if (!mongocrypt_status_ok(status)) { + return false; } + + CLIENT_ERR("The domain of double values specified by the min, max, and precision cannot be represented in " + "fewer than 53 bits. min: %g, max: %g, precision: %" PRId32, + args.min.value, + args.max.value, + args.precision.value); + return false; } + + // If we are not in range_v2, then we don't care about the error returned + // from canUsePrecisionMode so we can reset the status. + _mongocrypt_status_reset(status); } if (use_precision_mode) { // Take a number of xxxx.ppppp and truncate it xxxx.ppp if precision = 3. // We do not change the digits before the decimal place. - double v_prime = trunc(args.value * exp10Double(args.precision.value)) / exp10Double(args.precision.value); - int64_t v_prime2 = (int64_t)((v_prime - args.min.value) * exp10Double(args.precision.value)); + int64_t v_prime = (int64_t)(trunc(args.value * exp10Double(args.precision.value))); + int64_t scaled_min = (int64_t)(args.min.value * exp10Double(args.precision.value)); + int64_t v_prime2 = v_prime - scaled_min; BSON_ASSERT(v_prime2 < INT64_MAX && v_prime2 >= 0); @@ -298,7 +428,7 @@ bool mc_getTypeInfoDouble(mc_getTypeInfoDouble_args_t args, mc_OSTType_Double *o * @param dec * @return mlib_int128 */ -static mlib_int128 dec128_to_int128(mc_dec128 dec) { +static mlib_int128 dec128_to_uint128(mc_dec128 dec) { // Only normal numbers BSON_ASSERT(mc_dec128_is_finite(dec)); BSON_ASSERT(!mc_dec128_is_nan(dec)); @@ -313,6 +443,7 @@ static mlib_int128 dec128_to_int128(mc_dec128 dec) { // Decimal128: int32_t exp = ((int32_t)mc_dec128_get_biased_exp(dec)) - MC_DEC128_EXPONENT_BIAS; // We will scale up/down based on whether it is negative: + BSON_ASSERT(abs(exp) <= UINT8_MAX); mlib_int128 e1 = mlib_int128_pow10((uint8_t)abs(exp)); if (exp < 0) { ret = mlib_int128_div(ret, e1); @@ -323,15 +454,176 @@ static mlib_int128 dec128_to_int128(mc_dec128 dec) { return ret; } +// (2^127 - 1) = the maximum signed 128-bit integer value, as a decimal128 +#define INT_128_MAX_AS_DECIMAL mc_dec128_from_string("170141183460469231731687303715884105727") +// (2^128 - 1) = the max unsigned 128-bit integer value, as a decimal128 +#define UINT_128_MAX_AS_DECIMAL mc_dec128_from_string("340282366920938463463374607431768211455") + +static mlib_int128 dec128_to_int128(mc_dec128 dec) { + BSON_ASSERT(mc_dec128_less(dec, INT_128_MAX_AS_DECIMAL)); + + bool negative = false; + + if (mc_dec128_is_negative(dec)) { + negative = true; + dec = mc_dec128_mul(MC_DEC128(-1), dec); + } + + mlib_int128 ret_val = dec128_to_uint128(dec); + + if (negative) { + ret_val = mlib_int128_mul(MLIB_INT128(-1), ret_val); + } + + return ret_val; +} + +bool ceil_log2_int128(mlib_int128 i, uint32_t *maxBitsOut, mongocrypt_status_t *status) { + if (mlib_int128_eq(i, MLIB_INT128(0))) { + CLIENT_ERR("Invalid input to ceil_log2_int128 function. Input cannot be 0."); + return false; + } + + uint32_t clz = (uint32_t)_mlibCountLeadingZeros_u128(i); + uint32_t bits; + + // if i & (i - 1) == 0 + if (mlib_int128_eq((mlib_int128_bitand(i, (mlib_int128_sub(i, MLIB_INT128(1))))), MLIB_INT128(0))) { + bits = 128 - clz - 1; + } else { + bits = 128 - clz; + } + *maxBitsOut = bits; + return true; +} + +bool mc_canUsePrecisionModeDecimal(mc_dec128 min, + mc_dec128 max, + int32_t precision, + uint32_t *maxBitsOut, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(maxBitsOut); + BSON_ASSERT(precision >= 0); + + if (!mc_dec128_is_finite(max)) { + CLIENT_ERR("Invalid upper bound for Decimal128 precision. Max is infinite."); + return false; + } + + if (!mc_dec128_is_finite(min)) { + CLIENT_ERR("Invalid lower bound for Decimal128 precision. Min is infinite."); + return false; + } + + if (mc_dec128_greater_equal(min, max)) { + CLIENT_ERR("Invalid upper and lower bounds for Decimal128 precision. Min must be strictly less than max. min: " + "%s, max: %s", + mc_dec128_to_string(min).str, + mc_dec128_to_string(max).str); + return false; + } + + mc_dec128 scaled_max = mc_dec128_scale(max, precision); + mc_dec128 scaled_min = mc_dec128_scale(min, precision); + + mc_dec128 scaled_max_trunc = mc_dec128_round_integral_ex(scaled_max, MC_DEC128_ROUND_TOWARD_ZERO, NULL); + mc_dec128 scaled_min_trunc = mc_dec128_round_integral_ex(scaled_min, MC_DEC128_ROUND_TOWARD_ZERO, NULL); + + if (mc_dec128_not_equal(scaled_max, scaled_max_trunc)) { + CLIENT_ERR("Invalid upper bound for Decimal128 precision. Fractional digits must be less than " + "the specified precision value. max: %s, precision: %" PRId32, + mc_dec128_to_string(max).str, + precision); + return false; + } + + if (mc_dec128_not_equal(scaled_min, scaled_min_trunc)) { + CLIENT_ERR("Invalid lower bound for Decimal128 precision. Fractional digits must be less than " + "the specified precision value. min: %s, precision: %" PRId32, + mc_dec128_to_string(min).str, + precision); + return false; + } + + if (mc_dec128_greater(mc_dec128_abs(scaled_max), INT_128_MAX_AS_DECIMAL)) { + CLIENT_ERR("Invalid upper bound for Decimal128 precision. Absolute scaled value must be less than " + "or equal to %s. max: %s", + mc_dec128_to_string(INT_128_MAX_AS_DECIMAL).str, + mc_dec128_to_string(max).str); + return false; + } + + if (mc_dec128_greater(mc_dec128_abs(scaled_min), INT_128_MAX_AS_DECIMAL)) { + CLIENT_ERR("Invalid lower bound for Decimal128 precision. Absolute scaled value must be less than " + "or equal to %s. min: %s", + mc_dec128_to_string(INT_128_MAX_AS_DECIMAL).str, + mc_dec128_to_string(min).str); + return false; + } + + mc_dec128 t_1 = mc_dec128_sub(scaled_max, scaled_min); + mc_dec128 t_4 = mc_dec128_sub(UINT_128_MAX_AS_DECIMAL, t_1); + + // t_5 = floor(log10(t_4)) - 1; + mc_dec128 t_5 = mc_dec128_sub(mc_dec128_round_integral_ex(mc_dec128_log10(t_4), MC_DEC128_ROUND_TOWARD_ZERO, NULL), + MC_DEC128(1)); + + // We convert precision to a double so we can avoid warning C4146 on Windows. + mc_dec128 prc_dec = mc_dec128_from_double((double)precision); + + if (mc_dec128_less(t_5, prc_dec)) { + CLIENT_ERR("Invalid value for precision. precision: %" PRId32, precision); + return false; + } + + mlib_int128 i_1 = dec128_to_int128(scaled_max); + mlib_int128 i_2 = dec128_to_int128(scaled_min); + + // Because we have guaranteed earlier that max is greater than min, we can + // subtract these values and guarantee that taking their unsigned + // representation will yield the actual range result. + mlib_int128 range128 = mlib_int128_sub(i_1, i_2); + + if (precision > UINT8_MAX) { + CLIENT_ERR("Invalid value for precision. Must be less than 255. precision: %" PRId32, precision); + return false; + } + + mlib_int128 i_3 = mlib_int128_add(range128, mlib_int128_pow10((uint8_t)precision)); + if (!ceil_log2_int128(i_3, maxBitsOut, status)) { + return false; + } + + if (*maxBitsOut >= 128) { + return false; + } + + return true; +} + bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args, mc_OSTType_Decimal128 *out, - mongocrypt_status_t *status) { + mongocrypt_status_t *status, + bool use_range_v2) { /// Basic param checks if (args.min.set != args.max.set || args.min.set != args.precision.set) { CLIENT_ERR("min, max, and precision must all be set or must all be unset"); return false; } + if (args.precision.set) { + if (args.precision.value < 0) { + CLIENT_ERR("Precision must be non-negative, but got %" PRId32, args.precision.value); + return false; + } + + mc_dec128 scaled = mc_dec128_scale(MC_DEC128(1), args.precision.value); + if (!mc_dec128_is_finite(scaled)) { + CLIENT_ERR("Precision is too large and cannot be used to calculate the scaled range bounds"); + return false; + } + } + // We only accept normal numbers if (mc_dec128_is_inf(args.value) || mc_dec128_is_nan(args.value)) { CLIENT_ERR("Infinity and Nan Decimal128 values are not supported."); @@ -375,45 +667,27 @@ bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args, // full range. bool use_precision_mode = false; // The number of bits required to hold the result (used for precision mode) - uint8_t bits_range = 0; + uint32_t bits_range = 0; if (args.precision.set) { - // Subnormal representations can support up to 5x10^-6182 as a number - if (args.precision.value > 6182) { - CLIENT_ERR("Precision must be between 0 and 6182 inclusive, got: %" PRIu32, args.precision.value); - return false; - } + use_precision_mode = + mc_canUsePrecisionModeDecimal(args.min.value, args.max.value, args.precision.value, &bits_range, status); - // max - min - mc_dec128 bounds_n1 = mc_dec128_sub(args.max.value, args.min.value); - // The size of [min, max]: (max - min) + 1 - mc_dec128 bounds = mc_dec128_add(bounds_n1, MC_DEC128_ONE); - - // We can overflow if max = max_dec128 and min = min_dec128 so make sure - // we have finite number after we do subtraction - if (mc_dec128_is_finite(bounds)) { - // This creates a range which is wider then we permit by our min/max - // bounds check with the +1 but it is as the algorithm is written in - // WRITING-11907. - mc_dec128 precision_scaled_bounds = mc_dec128_scale(bounds, args.precision.value); - /// The number of bits required to hold the result for the given - /// precision (as decimal) - mc_dec128 bits_range_dec = mc_dec128_log2(precision_scaled_bounds); - - if (mc_dec128_is_finite(bits_range_dec) && mc_dec128_less(bits_range_dec, MC_DEC128(128))) { - // We need fewer than 128 bits to hold the result. But round up, - // just to be sure: - int64_t r = - mc_dec128_to_int64(mc_dec128_round_integral_ex(bits_range_dec, MC_DEC128_ROUND_UPWARD, NULL)); - BSON_ASSERT(r >= 0); - BSON_ASSERT(r <= UINT8_MAX); - // We've computed the proper 'bits_range' - bits_range = (uint8_t)r; - - if (bits_range < 128) { - use_precision_mode = true; - } + if (use_range_v2 && !use_precision_mode) { + if (!mongocrypt_status_ok(status)) { + return false; } + + CLIENT_ERR("The domain of decimal values specified by the min, max, and precision cannot be represented in " + "fewer than 128 bits. min: %s, max: %s, precision: %" PRIu32, + mc_dec128_to_string(args.min.value).str, + mc_dec128_to_string(args.max.value).str, + args.precision.value); + return false; } + + // If we are not in range_v2, then we don't care about the error returned + // from canUsePrecisionMode so we can reset the status. + _mongocrypt_status_reset(status); } // Constant zero @@ -456,9 +730,9 @@ bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args, v_prime2 = mc_dec128_round_integral_ex(v_prime2, MC_DEC128_ROUND_TOWARD_ZERO, NULL); BSON_ASSERT(mc_dec128_less(mc_dec128_log2(v_prime2), MC_DEC128(128))); - + BSON_ASSERT(bits_range < 128); // Resulting OST maximum - mlib_int128 ost_max = mlib_int128_sub(mlib_int128_pow2(bits_range), i128_one); + mlib_int128 ost_max = mlib_int128_sub(mlib_int128_pow2((uint8_t)bits_range), i128_one); // Now we need to get the Decimal128 out as a 128-bit integer // But Decimal128 does not support conversion to Int128. @@ -575,3 +849,23 @@ bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args, } #endif // defined MONGOCRYPT_HAVE_DECIMAL128_SUPPORT + +const int64_t mc_FLERangeSparsityDefault = 2; +const int32_t mc_FLERangeTrimFactorDefault = 6; + +int32_t trimFactorDefault(size_t maxlen, mc_optional_int32_t trimFactor, bool use_range_v2) { + if (trimFactor.set) { + return trimFactor.value; + } + + if (!use_range_v2) { + // Preserve old default. + return 0; + } + + if (bson_cmp_greater_su(mc_FLERangeTrimFactorDefault, maxlen - 1)) { + return (int32_t)(maxlen - 1); + } else { + return mc_FLERangeTrimFactorDefault; + } +} diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h index 30809ee..907bd97 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h @@ -17,18 +17,6 @@ // mc-range-mincover-generator.template.h is meant to be included in another // source file. -// TODO: replace `CONCAT` with `BSON_CONCAT` after libbson dependency is -// upgraded to 1.20.0 or higher. -#ifndef CONCAT -#define CONCAT_1(a, b) a##b -#define CONCAT(a, b) CONCAT_1(a, b) -#endif -// TODO: replace `CONCAT3` with `BSON_CONCAT3` after libbson dependency is -// upgraded to 1.20.0 or higher. -#ifndef CONCAT3 -#define CONCAT3(a, b, c) CONCAT(a, CONCAT(b, c)) -#endif - #if !(defined(UINT_T) && defined(UINT_C) && defined(UINT_FMT_S) && defined(DECORATE_NAME)) #ifdef __INTELLISENSE__ #define UINT_T uint32_t @@ -101,6 +89,7 @@ typedef struct { UINT_T _rangeMin; UINT_T _rangeMax; size_t _sparsity; + int32_t _trimFactor; // _maxlen is the maximum bit length of edges in the mincover. size_t _maxlen; } DECORATE_NAME(MinCoverGenerator); @@ -110,7 +99,9 @@ static inline DECORATE_NAME(MinCoverGenerator) UINT_T rangeMax, UINT_T max, size_t sparsity, - mongocrypt_status_t *status) { + mc_optional_int32_t opt_trimFactor, + mongocrypt_status_t *status, + bool use_range_v2) { BSON_ASSERT_PARAM(status); if (UINT_COMPARE(rangeMin, rangeMax) > 0) { @@ -131,11 +122,25 @@ static inline DECORATE_NAME(MinCoverGenerator) CLIENT_ERR("Sparsity must be > 0"); return NULL; } + size_t maxlen = (size_t)BITS - DECORATE_NAME(mc_count_leading_zeros)(max); + int32_t trimFactor = trimFactorDefault(maxlen, opt_trimFactor, use_range_v2); + if (trimFactor != 0 && bson_cmp_greater_equal_su(trimFactor, maxlen)) { + CLIENT_ERR("Trim factor must be less than the number of bits (%ld) used to represent an element of the domain, " + "but got %" PRId32, + maxlen, + trimFactor); + return NULL; + } + if (trimFactor < 0) { + CLIENT_ERR("Trim factor must be >= 0, but got (%" PRId32 ")", trimFactor); + return NULL; + } DECORATE_NAME(MinCoverGenerator) *mcg = bson_malloc0(sizeof(DECORATE_NAME(MinCoverGenerator))); mcg->_rangeMin = rangeMin; mcg->_rangeMax = rangeMax; mcg->_maxlen = (size_t)BITS - DECORATE_NAME(mc_count_leading_zeros)(max); mcg->_sparsity = sparsity; + mcg->_trimFactor = trimFactor; return mcg; } @@ -164,7 +169,9 @@ static inline bool DECORATE_NAME(MinCoverGenerator_isLevelStored)(DECORATE_NAME( size_t maskedBits) { BSON_ASSERT_PARAM(mcg); size_t level = mcg->_maxlen - maskedBits; - return 0 == maskedBits || 0 == (level % mcg->_sparsity); + BSON_ASSERT(bson_in_range_size_t_signed(mcg->_trimFactor)); + size_t trimFactor_sz = (size_t)mcg->_trimFactor; + return 0 == maskedBits || (level >= trimFactor_sz && 0 == (level % mcg->_sparsity)); } char * @@ -219,6 +226,11 @@ static inline mc_mincover_t *DECORATE_NAME(MinCoverGenerator_minCover)(DECORATE_ return mc; } +static inline int32_t DECORATE_NAME(MinCoverGenerator_usedTrimFactor)(DECORATE_NAME(MinCoverGenerator) * mcg) { + BSON_ASSERT_PARAM(mcg); + return mcg->_trimFactor; +} + // adjustBounds increments *lowerBound if includeLowerBound is false and // decrements *upperBound if includeUpperBound is false. // lowerBound, min, upperBound, and max are expected to come from the result diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-private.h index 3e073b0..2129dff 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-private.h @@ -33,6 +33,9 @@ const char *mc_mincover_get(mc_mincover_t *mincover, size_t index); // mc_mincover_len returns the number of represented mincover. size_t mc_mincover_len(mc_mincover_t *mincover); +// Return the trimFactor that was used to generate this mincover. +int32_t mc_mincover_get_used_trimFactor(const mc_mincover_t *mincover); + // mc_mincover_destroys frees `mincover`. void mc_mincover_destroy(mc_mincover_t *mincover); @@ -44,12 +47,14 @@ typedef struct { mc_optional_int32_t min; mc_optional_int32_t max; size_t sparsity; + mc_optional_int32_t trimFactor; } mc_getMincoverInt32_args_t; // mc_getMincoverInt32 implements the Mincover Generation algorithm described in // SERVER-68600 for int32_t. mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args, - mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT; + mongocrypt_status_t *status, + bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT; typedef struct { int64_t lowerBound; @@ -59,12 +64,14 @@ typedef struct { mc_optional_int64_t min; mc_optional_int64_t max; size_t sparsity; + mc_optional_int32_t trimFactor; } mc_getMincoverInt64_args_t; // mc_getMincoverInt64 implements the Mincover Generation algorithm described in // SERVER-68600 for int64_t. mc_mincover_t *mc_getMincoverInt64(mc_getMincoverInt64_args_t args, - mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT; + mongocrypt_status_t *status, + bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT; typedef struct { double lowerBound; @@ -74,13 +81,15 @@ typedef struct { size_t sparsity; mc_optional_double_t min; mc_optional_double_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_getMincoverDouble_args_t; // mc_getMincoverDouble implements the Mincover Generation algorithm described // in SERVER-68600 for double. mc_mincover_t *mc_getMincoverDouble(mc_getMincoverDouble_args_t args, - mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT; + mongocrypt_status_t *status, + bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT; #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT typedef struct { @@ -90,13 +99,15 @@ typedef struct { bool includeUpperBound; size_t sparsity; mc_optional_dec128_t min, max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_getMincoverDecimal128_args_t; // mc_getMincoverDecimal128 implements the Mincover Generation algorithm // described in SERVER-68600 for Decimal128 (as mc_dec128). mc_mincover_t *mc_getMincoverDecimal128(mc_getMincoverDecimal128_args_t args, - mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT; + mongocrypt_status_t *status, + bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT; #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT #endif /* MC_RANGE_MINCOVER_PRIVATE_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c index 514d24c..635ae6c 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c @@ -20,13 +20,14 @@ #include "mc-array-private.h" #include "mc-range-edge-generation-private.h" // mc_count_leading_zeros_u32 -#include "mc-range-encoding-private.h" // mc_getTypeInfo32 +#include "mc-range-encoding-private.h" // mc_getTypeInfo32, trimFactorDefault #include "mc-range-mincover-private.h" #include "mongocrypt-private.h" struct _mc_mincover_t { /* mincover is an array of `char*` edge strings. */ mc_array_t mincover; + int32_t usedTrimFactor; // The `trimFactor` that was used to produce this mincover. }; static mc_mincover_t *mc_mincover_new(void) { @@ -48,6 +49,10 @@ size_t mc_mincover_len(mc_mincover_t *mincover) { return mincover->mincover.len; } +int32_t mc_mincover_get_used_trimFactor(const mc_mincover_t *mincover) { + return mincover->usedTrimFactor; +} + void mc_mincover_destroy(mc_mincover_t *mincover) { if (NULL == mincover) { return; @@ -127,7 +132,7 @@ void mc_mincover_destroy(mc_mincover_t *mincover) { } else \ (void)0 -mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args, mongocrypt_status_t *status) { +mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args, mongocrypt_status_t *status, bool use_range_v2) { BSON_ASSERT_PARAM(status); CHECK_BOUNDS(args, PRId32, IDENTITY, LESSTHAN); mc_OSTType_Int32 a, b; @@ -149,16 +154,18 @@ mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args, mongocrypt_s return NULL; } - MinCoverGenerator_u32 *mcg = MinCoverGenerator_new_u32(a.value, b.value, a.max, args.sparsity, status); + MinCoverGenerator_u32 *mcg = + MinCoverGenerator_new_u32(a.value, b.value, a.max, args.sparsity, args.trimFactor, status, use_range_v2); if (!mcg) { return NULL; } mc_mincover_t *mc = MinCoverGenerator_minCover_u32(mcg); + mc->usedTrimFactor = MinCoverGenerator_usedTrimFactor_u32(mcg); MinCoverGenerator_destroy_u32(mcg); return mc; } -mc_mincover_t *mc_getMincoverInt64(mc_getMincoverInt64_args_t args, mongocrypt_status_t *status) { +mc_mincover_t *mc_getMincoverInt64(mc_getMincoverInt64_args_t args, mongocrypt_status_t *status, bool use_range_v2) { BSON_ASSERT_PARAM(status); CHECK_BOUNDS(args, PRId64, IDENTITY, LESSTHAN); mc_OSTType_Int64 a, b; @@ -180,18 +187,20 @@ mc_mincover_t *mc_getMincoverInt64(mc_getMincoverInt64_args_t args, mongocrypt_s return NULL; } - MinCoverGenerator_u64 *mcg = MinCoverGenerator_new_u64(a.value, b.value, a.max, args.sparsity, status); + MinCoverGenerator_u64 *mcg = + MinCoverGenerator_new_u64(a.value, b.value, a.max, args.sparsity, args.trimFactor, status, use_range_v2); if (!mcg) { return NULL; } mc_mincover_t *mc = MinCoverGenerator_minCover_u64(mcg); + mc->usedTrimFactor = MinCoverGenerator_usedTrimFactor_u64(mcg); MinCoverGenerator_destroy_u64(mcg); return mc; } // mc_getMincoverDouble implements the Mincover Generation algorithm described // in SERVER-68600 for double. -mc_mincover_t *mc_getMincoverDouble(mc_getMincoverDouble_args_t args, mongocrypt_status_t *status) { +mc_mincover_t *mc_getMincoverDouble(mc_getMincoverDouble_args_t args, mongocrypt_status_t *status, bool use_range_v2) { BSON_ASSERT_PARAM(status); CHECK_BOUNDS(args, "g", IDENTITY, LESSTHAN); @@ -201,7 +210,8 @@ mc_mincover_t *mc_getMincoverDouble(mc_getMincoverDouble_args_t args, mongocrypt .max = args.max, .precision = args.precision}, &a, - status)) { + status, + use_range_v2)) { return NULL; } if (!mc_getTypeInfoDouble((mc_getTypeInfoDouble_args_t){.value = args.upperBound, @@ -209,7 +219,8 @@ mc_mincover_t *mc_getMincoverDouble(mc_getMincoverDouble_args_t args, mongocrypt .max = args.max, .precision = args.precision}, &b, - status)) { + status, + use_range_v2)) { return NULL; } @@ -220,17 +231,20 @@ mc_mincover_t *mc_getMincoverDouble(mc_getMincoverDouble_args_t args, mongocrypt return NULL; } - MinCoverGenerator_u64 *mcg = MinCoverGenerator_new_u64(a.value, b.value, a.max, args.sparsity, status); + MinCoverGenerator_u64 *mcg = + MinCoverGenerator_new_u64(a.value, b.value, a.max, args.sparsity, args.trimFactor, status, use_range_v2); if (!mcg) { return NULL; } mc_mincover_t *mc = MinCoverGenerator_minCover_u64(mcg); + mc->usedTrimFactor = MinCoverGenerator_usedTrimFactor_u64(mcg); MinCoverGenerator_destroy_u64(mcg); return mc; } #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT -mc_mincover_t *mc_getMincoverDecimal128(mc_getMincoverDecimal128_args_t args, mongocrypt_status_t *status) { +mc_mincover_t * +mc_getMincoverDecimal128(mc_getMincoverDecimal128_args_t args, mongocrypt_status_t *status, bool use_range_v2) { BSON_ASSERT_PARAM(status); #define ToString(Dec) (mc_dec128_to_string(Dec).str) CHECK_BOUNDS(args, "s", ToString, mc_dec128_less); @@ -241,7 +255,8 @@ mc_mincover_t *mc_getMincoverDecimal128(mc_getMincoverDecimal128_args_t args, mo .max = args.max, .precision = args.precision}, &a, - status)) { + status, + use_range_v2)) { return NULL; } if (!mc_getTypeInfoDecimal128((mc_getTypeInfoDecimal128_args_t){.value = args.upperBound, @@ -249,7 +264,8 @@ mc_mincover_t *mc_getMincoverDecimal128(mc_getMincoverDecimal128_args_t args, mo .max = args.max, .precision = args.precision}, &b, - status)) { + status, + use_range_v2)) { return NULL; } @@ -260,11 +276,13 @@ mc_mincover_t *mc_getMincoverDecimal128(mc_getMincoverDecimal128_args_t args, mo return NULL; } - MinCoverGenerator_u128 *mcg = MinCoverGenerator_new_u128(a.value, b.value, a.max, args.sparsity, status); + MinCoverGenerator_u128 *mcg = + MinCoverGenerator_new_u128(a.value, b.value, a.max, args.sparsity, args.trimFactor, status, use_range_v2); if (!mcg) { return NULL; } mc_mincover_t *mc = MinCoverGenerator_minCover_u128(mcg); + mc->usedTrimFactor = MinCoverGenerator_usedTrimFactor_u128(mcg); MinCoverGenerator_destroy_u128(mcg); return mc; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h index 0df6725..014f22d 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h @@ -36,7 +36,8 @@ typedef struct { } max; int64_t sparsity; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; + mc_optional_int32_t trimFactor; } mc_RangeOpts_t; /* mc_RangeOpts_parse parses a BSON document into mc_RangeOpts_t. @@ -45,10 +46,11 @@ typedef struct { * "min": BSON value, * "max": BSON value, * "sparsity": Int64, - * "precision": Optional + * "precision": Optional, + * "trimFactor": Optional, * } */ -bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, mongocrypt_status_t *status); +bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, bool use_range_v2, mongocrypt_status_t *status); /* * mc_RangeOpts_to_FLE2RangeInsertSpec creates a placeholder value to be @@ -69,6 +71,7 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, mongocrypt_status_ bool mc_RangeOpts_to_FLE2RangeInsertSpec(const mc_RangeOpts_t *ro, const bson_t *v, bson_t *out, + bool use_range_v2, mongocrypt_status_t *status); /* mc_RangeOpts_appendMin appends the minimum value of the range for a given @@ -89,6 +92,16 @@ bool mc_RangeOpts_appendMax(const mc_RangeOpts_t *ro, bson_t *out, mongocrypt_status_t *status); +/* mc_RangeOpts_appendTrimFactor appends the trim factor of the field. If `ro->trimFactor` is unset, + * defaults to 0. Errors if `ro->trimFactor` is out of bounds based on the size of the domain + * computed from `valueType`, `ro->min` and `ro->max`. */ +bool mc_RangeOpts_appendTrimFactor(const mc_RangeOpts_t *ro, + bson_type_t valueType, + const char *fieldName, + bson_t *out, + mongocrypt_status_t *status, + bool use_range_v2); + void mc_RangeOpts_cleanup(mc_RangeOpts_t *ro); #endif // MC_RANGEOPTS_PRIVATE_H diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c b/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c index 5de8df5..4a9e4c6 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c @@ -17,16 +17,21 @@ #include "mc-rangeopts-private.h" #include "mc-check-conversions-private.h" +#include "mc-range-edge-generation-private.h" // mc_count_leading_zeros_XX +#include "mc-range-encoding-private.h" // mc_getTypeInfoXX #include "mongocrypt-private.h" #include "mongocrypt-util-private.h" // mc_bson_type_to_string #include // DBL_MAX +#define CLIENT_ERR_PREFIXED_HELPER(Prefix, ErrorString, ...) CLIENT_ERR(Prefix ": " ErrorString, ##__VA_ARGS__) +#define CLIENT_ERR_PREFIXED(ErrorString, ...) CLIENT_ERR_PREFIXED_HELPER(ERROR_PREFIX, ErrorString, ##__VA_ARGS__) + // Common logic for testing field name, tracking duplication, and presence. -#define IF_FIELD(Name, ErrorPrefix) \ +#define IF_FIELD(Name) \ if (0 == strcmp(field, #Name)) { \ if (has_##Name) { \ - CLIENT_ERR("%sUnexpected duplicate field '" #Name "'", ErrorPrefix); \ + CLIENT_ERR_PREFIXED("Unexpected duplicate field '" #Name "'"); \ return false; \ } \ has_##Name = true; @@ -35,17 +40,17 @@ continue; \ } -#define CHECK_HAS(Name, ErrorPrefix) \ +#define CHECK_HAS(Name) \ if (!has_##Name) { \ - CLIENT_ERR("%sMissing field '" #Name "'", ErrorPrefix); \ + CLIENT_ERR_PREFIXED("Missing field '" #Name "'"); \ return false; \ } -bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, mongocrypt_status_t *status) { - bson_iter_t iter; - bool has_min = false, has_max = false, has_sparsity = false, has_precision = false; - const char *const error_prefix = "Error parsing RangeOpts: "; +#define ERROR_PREFIX "Error parsing RangeOpts" +bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, bool use_range_v2, mongocrypt_status_t *status) { + bson_iter_t iter = {0}; + bool has_min = false, has_max = false, has_sparsity = false, has_precision = false, has_trimFactor = false; BSON_ASSERT_PARAM(ro); BSON_ASSERT_PARAM(in); BSON_ASSERT(status || true); @@ -54,7 +59,7 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, mongocrypt_status_ ro->bson = bson_copy(in); if (!bson_iter_init(&iter, ro->bson)) { - CLIENT_ERR("%sInvalid BSON", error_prefix); + CLIENT_ERR_PREFIXED("Invalid BSON"); return false; } @@ -62,74 +67,91 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, mongocrypt_status_ const char *field = bson_iter_key(&iter); BSON_ASSERT(field); - IF_FIELD(min, error_prefix) + IF_FIELD(min) ro->min.set = true; ro->min.value = iter; END_IF_FIELD - IF_FIELD(max, error_prefix) + IF_FIELD(max) ro->max.set = true; ro->max.value = iter; END_IF_FIELD - IF_FIELD(sparsity, error_prefix) + IF_FIELD(sparsity) if (!BSON_ITER_HOLDS_INT64(&iter)) { - CLIENT_ERR("%sExpected int64 for sparsity, got: %s", - error_prefix, - mc_bson_type_to_string(bson_iter_type(&iter))); + CLIENT_ERR_PREFIXED("Expected int64 for sparsity, got: %s", mc_bson_type_to_string(bson_iter_type(&iter))); return false; }; ro->sparsity = bson_iter_int64(&iter); END_IF_FIELD - IF_FIELD(precision, error_prefix) { + IF_FIELD(precision) { if (!BSON_ITER_HOLDS_INT32(&iter)) { - CLIENT_ERR("%s'precision' must be an int32", error_prefix); + CLIENT_ERR_PREFIXED("'precision' must be an int32"); + return false; + } + int32_t val = bson_iter_int32(&iter); + if (val < 0) { + CLIENT_ERR_PREFIXED("'precision' must be non-negative"); return false; } + ro->precision = OPT_I32(val); + } + END_IF_FIELD + + IF_FIELD(trimFactor) { + if (!BSON_ITER_HOLDS_INT32(&iter)) { + CLIENT_ERR_PREFIXED("Expected int32 for trimFactor, got: %s", + mc_bson_type_to_string(bson_iter_type(&iter))); + return false; + }; int32_t val = bson_iter_int32(&iter); if (val < 0) { - CLIENT_ERR("%s'precision' must be non-negative", error_prefix); + CLIENT_ERR_PREFIXED("'trimFactor' must be non-negative"); return false; } - ro->precision = OPT_U32((uint32_t)val); + ro->trimFactor = OPT_I32(val); } END_IF_FIELD - CLIENT_ERR("%sUnrecognized field: '%s'", error_prefix, field); + CLIENT_ERR_PREFIXED("Unrecognized field: '%s'", field); return false; } // Do not error if min/max are not present. min/max are optional. - CHECK_HAS(sparsity, error_prefix); // Do not error if precision is not present. Precision is optional and only // applies to double/decimal128. + // Do not error if trimFactor is not present. It is optional. + + if (!has_sparsity && use_range_v2) { + ro->sparsity = mc_FLERangeSparsityDefault; + } // Expect precision only to be set for double or decimal128. if (has_precision) { if (!ro->min.set) { - CLIENT_ERR("setting precision requires min"); + CLIENT_ERR_PREFIXED("setting precision requires min"); return false; } bson_type_t minType = bson_iter_type(&ro->min.value); if (minType != BSON_TYPE_DOUBLE && minType != BSON_TYPE_DECIMAL128) { - CLIENT_ERR("expected 'precision' to be set with double or decimal128 " - "index, but got: %s min", - mc_bson_type_to_string(minType)); + CLIENT_ERR_PREFIXED("expected 'precision' to be set with double or decimal128 " + "index, but got: %s min", + mc_bson_type_to_string(minType)); return false; } if (!ro->max.set) { - CLIENT_ERR("setting precision requires max"); + CLIENT_ERR_PREFIXED("setting precision requires max"); return false; } bson_type_t maxType = bson_iter_type(&ro->max.value); if (maxType != BSON_TYPE_DOUBLE && maxType != BSON_TYPE_DECIMAL128) { - CLIENT_ERR("expected 'precision' to be set with double or decimal128 " - "index, but got: %s max", - mc_bson_type_to_string(maxType)); + CLIENT_ERR_PREFIXED("expected 'precision' to be set with double or decimal128 " + "index, but got: %s max", + mc_bson_type_to_string(maxType)); return false; } } @@ -138,10 +160,10 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, mongocrypt_status_ if (ro->min.set && ro->max.set) { bson_type_t minType = bson_iter_type(&ro->min.value), maxType = bson_iter_type(&ro->max.value); if (minType != maxType) { - CLIENT_ERR("expected 'min' and 'max' to be same type, but got: %s " - "min and %s max", - mc_bson_type_to_string(minType), - mc_bson_type_to_string(maxType)); + CLIENT_ERR_PREFIXED("expected 'min' and 'max' to be same type, but got: %s " + "min and %s max", + mc_bson_type_to_string(minType), + mc_bson_type_to_string(maxType)); return false; } } @@ -152,7 +174,8 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, mongocrypt_status_ bson_type_t minType = bson_iter_type(&ro->min.value); if (minType == BSON_TYPE_DOUBLE || minType == BSON_TYPE_DECIMAL128) { if (!has_precision) { - CLIENT_ERR("expected 'precision' to be set with 'min' for %s", mc_bson_type_to_string(minType)); + CLIENT_ERR_PREFIXED("expected 'precision' to be set with 'min' for %s", + mc_bson_type_to_string(minType)); return false; } } @@ -162,39 +185,53 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, mongocrypt_status_ bson_type_t maxType = bson_iter_type(&ro->max.value); if (maxType == BSON_TYPE_DOUBLE || maxType == BSON_TYPE_DECIMAL128) { if (!has_precision) { - CLIENT_ERR("expected 'precision' to be set with 'max' for %s", mc_bson_type_to_string(maxType)); + CLIENT_ERR_PREFIXED("expected 'precision' to be set with 'max' for %s", + mc_bson_type_to_string(maxType)); return false; } } } } + if (ro->trimFactor.set) { + if (!use_range_v2) { + // Once `use_range_v2` is default true, this block may be removed. + CLIENT_ERR_PREFIXED("'trimFactor' is not supported for QE range v1"); + return false; + } + // At this point, we do not know the type of the field if min and max are unspecified. Wait to + // validate the value of trimFactor. + } + return true; } +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error making FLE2RangeInsertSpec" + bool mc_RangeOpts_to_FLE2RangeInsertSpec(const mc_RangeOpts_t *ro, const bson_t *v, bson_t *out, + bool use_range_v2, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(ro); BSON_ASSERT_PARAM(v); BSON_ASSERT_PARAM(out); BSON_ASSERT(status || true); - const char *const error_prefix = "Error making FLE2RangeInsertSpec: "; bson_iter_t v_iter; if (!bson_iter_init_find(&v_iter, v, "v")) { - CLIENT_ERR("Unable to find 'v' in input"); + CLIENT_ERR_PREFIXED("Unable to find 'v' in input"); return false; } bson_t child; if (!BSON_APPEND_DOCUMENT_BEGIN(out, "v", &child)) { - CLIENT_ERR("%sError appending to BSON", error_prefix); + CLIENT_ERR_PREFIXED("Error appending to BSON"); return false; } if (!bson_append_iter(&child, "v", 1, &v_iter)) { - CLIENT_ERR("%sError appending to BSON", error_prefix); + CLIENT_ERR_PREFIXED("Error appending to BSON"); return false; } @@ -209,17 +246,26 @@ bool mc_RangeOpts_to_FLE2RangeInsertSpec(const mc_RangeOpts_t *ro, if (ro->precision.set) { BSON_ASSERT(ro->precision.value <= INT32_MAX); if (!BSON_APPEND_INT32(&child, "precision", (int32_t)ro->precision.value)) { - CLIENT_ERR("%sError appending to BSON", error_prefix); + CLIENT_ERR_PREFIXED("Error appending to BSON"); + return false; + } + } + + if (use_range_v2) { + if (!mc_RangeOpts_appendTrimFactor(ro, bson_iter_type(&v_iter), "trimFactor", &child, status, use_range_v2)) { return false; } } if (!bson_append_document_end(out, &child)) { - CLIENT_ERR("%sError appending to BSON", error_prefix); + CLIENT_ERR_PREFIXED("Error appending to BSON"); return false; } return true; } +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error appending min to FLE2RangeInsertSpec" + bool mc_RangeOpts_appendMin(const mc_RangeOpts_t *ro, bson_type_t valueType, const char *fieldName, @@ -232,46 +278,49 @@ bool mc_RangeOpts_appendMin(const mc_RangeOpts_t *ro, if (ro->min.set) { if (bson_iter_type(&ro->min.value) != valueType) { - CLIENT_ERR("expected matching 'min' and value type. Got range option " - "'min' of type %s and value of type %s", - mc_bson_type_to_string(bson_iter_type(&ro->min.value)), - mc_bson_type_to_string(valueType)); + CLIENT_ERR_PREFIXED("expected matching 'min' and value type. Got range option " + "'min' of type %s and value of type %s", + mc_bson_type_to_string(bson_iter_type(&ro->min.value)), + mc_bson_type_to_string(valueType)); return false; } if (!bson_append_iter(out, fieldName, -1, &ro->min.value)) { - CLIENT_ERR("failed to append BSON"); + CLIENT_ERR_PREFIXED("failed to append BSON"); return false; } return true; } if (valueType == BSON_TYPE_INT32 || valueType == BSON_TYPE_INT64 || valueType == BSON_TYPE_DATE_TIME) { - CLIENT_ERR("Range option 'min' is required for type: %s", mc_bson_type_to_string(valueType)); + CLIENT_ERR_PREFIXED("Range option 'min' is required for type: %s", mc_bson_type_to_string(valueType)); return false; } else if (valueType == BSON_TYPE_DOUBLE) { if (!BSON_APPEND_DOUBLE(out, fieldName, -DBL_MAX)) { - CLIENT_ERR("failed to append BSON"); + CLIENT_ERR_PREFIXED("failed to append BSON"); return false; } } else if (valueType == BSON_TYPE_DECIMAL128) { #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT const bson_decimal128_t min = mc_dec128_to_bson_decimal128(MC_DEC128_LARGEST_NEGATIVE); if (!BSON_APPEND_DECIMAL128(out, fieldName, &min)) { - CLIENT_ERR("failed to append BSON"); + CLIENT_ERR_PREFIXED("failed to append BSON"); return false; } #else // ↑↑↑↑↑↑↑↑ With Decimal128 / Without ↓↓↓↓↓↓↓↓↓↓ - CLIENT_ERR("unsupported BSON type (Decimal128) for range: libmongocrypt " - "was built without extended Decimal128 support"); + CLIENT_ERR_PREFIXED("unsupported BSON type (Decimal128) for range: libmongocrypt " + "was built without extended Decimal128 support"); return false; #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT } else { - CLIENT_ERR("unsupported BSON type: %s for range", mc_bson_type_to_string(valueType)); + CLIENT_ERR_PREFIXED("unsupported BSON type: %s for range", mc_bson_type_to_string(valueType)); return false; } return true; } +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error appending max to FLE2RangeInsertSpec" + bool mc_RangeOpts_appendMax(const mc_RangeOpts_t *ro, bson_type_t valueType, const char *fieldName, @@ -284,46 +333,193 @@ bool mc_RangeOpts_appendMax(const mc_RangeOpts_t *ro, if (ro->max.set) { if (bson_iter_type(&ro->max.value) != valueType) { - CLIENT_ERR("expected matching 'max' and value type. Got range option " - "'max' of type %s and value of type %s", - mc_bson_type_to_string(bson_iter_type(&ro->max.value)), - mc_bson_type_to_string(valueType)); + CLIENT_ERR_PREFIXED("expected matching 'max' and value type. Got range option " + "'max' of type %s and value of type %s", + mc_bson_type_to_string(bson_iter_type(&ro->max.value)), + mc_bson_type_to_string(valueType)); return false; } if (!bson_append_iter(out, fieldName, -1, &ro->max.value)) { - CLIENT_ERR("failed to append BSON"); + CLIENT_ERR_PREFIXED("failed to append BSON"); return false; } return true; } if (valueType == BSON_TYPE_INT32 || valueType == BSON_TYPE_INT64 || valueType == BSON_TYPE_DATE_TIME) { - CLIENT_ERR("Range option 'max' is required for type: %s", mc_bson_type_to_string(valueType)); + CLIENT_ERR_PREFIXED("Range option 'max' is required for type: %s", mc_bson_type_to_string(valueType)); return false; } else if (valueType == BSON_TYPE_DOUBLE) { if (!BSON_APPEND_DOUBLE(out, fieldName, DBL_MAX)) { - CLIENT_ERR("failed to append BSON"); + CLIENT_ERR_PREFIXED("failed to append BSON"); return false; } } else if (valueType == BSON_TYPE_DECIMAL128) { #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT const bson_decimal128_t max = mc_dec128_to_bson_decimal128(MC_DEC128_LARGEST_POSITIVE); if (!BSON_APPEND_DECIMAL128(out, fieldName, &max)) { - CLIENT_ERR("failed to append BSON"); + CLIENT_ERR_PREFIXED("failed to append BSON"); return false; } #else // ↑↑↑↑↑↑↑↑ With Decimal128 / Without ↓↓↓↓↓↓↓↓↓↓ - CLIENT_ERR("unsupported BSON type (Decimal128) for range: libmongocrypt " - "was built without extended Decimal128 support"); + CLIENT_ERR_PREFIXED("unsupported BSON type (Decimal128) for range: libmongocrypt " + "was built without extended Decimal128 support"); return false; #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT } else { - CLIENT_ERR("unsupported BSON type: %s for range", mc_bson_type_to_string(valueType)); + CLIENT_ERR_PREFIXED("unsupported BSON type: %s for range", mc_bson_type_to_string(valueType)); return false; } return true; } +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error in getNumberOfBits" + +// Used to calculate max trim factor. Returns the number of bits required to represent any number in +// the domain. +bool mc_getNumberOfBits(const mc_RangeOpts_t *ro, + bson_type_t valueType, + uint32_t *bitsOut, + mongocrypt_status_t *status, + bool use_range_v2) { + BSON_ASSERT_PARAM(ro); + BSON_ASSERT_PARAM(bitsOut); + + // For each type, we use getTypeInfo to get the total number of values in the domain (-1) + // which tells us how many bits are needed to represent the whole domain. + // note - can't use a switch statement because of -Werror=switch-enum + if (valueType == BSON_TYPE_INT32) { + int32_t value = 0; + mc_optional_int32_t rmin = {false, 0}, rmax = {false, 0}; + if (ro->min.set) { + BSON_ASSERT(ro->max.set); + value = bson_iter_int32(&ro->min.value); + rmin = OPT_I32(value); + rmax = OPT_I32(bson_iter_int32(&ro->max.value)); + } + mc_getTypeInfo32_args_t args = {value, rmin, rmax}; + mc_OSTType_Int32 out; + if (!mc_getTypeInfo32(args, &out, status)) { + return false; + } + *bitsOut = 32 - (uint32_t)mc_count_leading_zeros_u32(out.max); + return true; + } else if (valueType == BSON_TYPE_INT64) { + int64_t value = 0; + mc_optional_int64_t rmin = {false, 0}, rmax = {false, 0}; + if (ro->min.set) { + BSON_ASSERT(ro->max.set); + value = bson_iter_int64(&ro->min.value); + rmin = OPT_I64(value); + rmax = OPT_I64(bson_iter_int64(&ro->max.value)); + } + mc_getTypeInfo64_args_t args = {value, rmin, rmax}; + mc_OSTType_Int64 out; + if (!mc_getTypeInfo64(args, &out, status)) { + return false; + } + *bitsOut = 64 - (uint32_t)mc_count_leading_zeros_u64(out.max); + return true; + } else if (valueType == BSON_TYPE_DATE_TIME) { + int64_t value = 0; + mc_optional_int64_t rmin = {false, 0}, rmax = {false, 0}; + if (ro->min.set) { + BSON_ASSERT(ro->max.set); + value = bson_iter_date_time(&ro->min.value); + rmin = OPT_I64(value); + rmax = OPT_I64(bson_iter_date_time(&ro->max.value)); + } + mc_getTypeInfo64_args_t args = {value, rmin, rmax}; + mc_OSTType_Int64 out; + if (!mc_getTypeInfo64(args, &out, status)) { + return false; + } + *bitsOut = 64 - (uint32_t)mc_count_leading_zeros_u64(out.max); + return true; + } else if (valueType == BSON_TYPE_DOUBLE) { + double value = 0; + mc_optional_double_t rmin = {false, 0}, rmax = {false, 0}; + mc_optional_int32_t prec = ro->precision; + if (ro->min.set) { + BSON_ASSERT(ro->max.set); + value = bson_iter_double(&ro->min.value); + rmin = OPT_DOUBLE(value); + rmax = OPT_DOUBLE(bson_iter_double(&ro->max.value)); + } + mc_getTypeInfoDouble_args_t args = {value, rmin, rmax, prec}; + mc_OSTType_Double out; + if (!mc_getTypeInfoDouble(args, &out, status, use_range_v2)) { + return false; + } + *bitsOut = 64 - (uint32_t)mc_count_leading_zeros_u64(out.max); + return true; + } +#if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT + else if (valueType == BSON_TYPE_DECIMAL128) { + mc_dec128 value = MC_DEC128_ZERO; + mc_optional_dec128_t rmin = {false, MC_DEC128_ZERO}, rmax = {false, MC_DEC128_ZERO}; + mc_optional_int32_t prec = ro->precision; + if (ro->min.set) { + BSON_ASSERT(ro->max.set); + value = mc_dec128_from_bson_iter(&ro->min.value); + rmin = OPT_MC_DEC128(value); + rmax = OPT_MC_DEC128(mc_dec128_from_bson_iter(&ro->max.value)); + } + mc_getTypeInfoDecimal128_args_t args = {value, rmin, rmax, prec}; + mc_OSTType_Decimal128 out; + if (!mc_getTypeInfoDecimal128(args, &out, status, use_range_v2)) { + return false; + } + *bitsOut = 128 - (uint32_t)mc_count_leading_zeros_u128(out.max); + return true; + } +#endif + CLIENT_ERR_PREFIXED("unsupported BSON type: %s for range", mc_bson_type_to_string(valueType)); + return false; +} + +#undef ERROR_PREFIX +#define ERROR_PREFIX "Error appending trim factor to FLE2RangeInsertSpec" + +bool mc_RangeOpts_appendTrimFactor(const mc_RangeOpts_t *ro, + bson_type_t valueType, + const char *fieldName, + bson_t *out, + mongocrypt_status_t *status, + bool use_range_v2) { + BSON_ASSERT_PARAM(ro); + BSON_ASSERT_PARAM(fieldName); + BSON_ASSERT_PARAM(out); + BSON_ASSERT(status || true); + + if (!ro->trimFactor.set) { + // A default `trimFactor` will be selected later with `trimFactorDefault` + return true; + } + + uint32_t nbits; + if (!mc_getNumberOfBits(ro, valueType, &nbits, status, use_range_v2)) { + return false; + } + // if nbits = 0, we want to allow trim factor = 0. + uint32_t test = nbits ? nbits : 1; + if (bson_cmp_greater_equal_su(ro->trimFactor.value, test)) { + CLIENT_ERR_PREFIXED("Trim factor (%d) must be less than the total number of bits (%d) used to represent " + "any element in the domain.", + ro->trimFactor.value, + nbits); + return false; + } + if (!BSON_APPEND_INT32(out, fieldName, ro->trimFactor.value)) { + CLIENT_ERR_PREFIXED("failed to append BSON"); + return false; + } + return true; +} + +#undef ERROR_PREFIX + void mc_RangeOpts_cleanup(mc_RangeOpts_t *ro) { if (!ro) { return; diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-tokens-private.h b/ext/libmongocrypt/libmongocrypt/src/mc-tokens-private.h index 2812a9c..e2aad7c 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-tokens-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mc-tokens-private.h @@ -24,7 +24,7 @@ * * v is a BSON value. It is the bytes after "e_name" in "element" in * https://bsonspec.org/spec.html. - * u is a "contention factor" counter. It is a uint64_t. + * u is a "contention factor". It is a uint64_t. * HMAC is the HMAC-SHA-256 function. * Integers are represented as uint64_t in little-endian. * @@ -40,11 +40,21 @@ * ESCDerivedFromDataToken = HMAC(ESCToken, v) * ECCDerivedFromDataToken = HMAC(ECCToken, v) * - * EDCDerivedFromDataTokenAndCounter = HMAC(EDCDerivedFromDataToken, u) - * ESCDerivedFromDataTokenAndCounter = HMAC(ESCDerivedFromDataToken, u) - * ECCDerivedFromDataTokenAndCounter = HMAC(ECCDerivedFromDataToken, u) + * EDCDerivedFromDataTokenAndContentionFactor = HMAC(EDCDerivedFromDataToken, u) + * ESCDerivedFromDataTokenAndContentionFactor = HMAC(ESCDerivedFromDataToken, u) + * ECCDerivedFromDataTokenAndContentionFactor = HMAC(ECCDerivedFromDataToken, u) + * + * EDCTwiceDerivedToken = HMAC(EDCDerivedFromDataTokenAndContentionFactor, 1) + + * ESCTwiceDerivedTagToken = HMAC(ESCDerivedFromDataTokenAndContentionFactor, 1) + * ESCTwiceDerivedValueToken = HMAC(ESCDerivedFromDataTokenAndContentionFactor, 2) + + * ECCTwiceDerivedTagToken = HMAC(ECCDerivedFromDataTokenAndContentionFactor, 1) + * ECCTwiceDerivedValueToken = HMAC(ECCDerivedFromDataTokenAndContentionFactor, 2) * * Note: ECC related tokens are used in FLE2v1 only. + * Further, ECCTwiceDerivedValue(Tag|Token) have been omitted entirely. + * The above comment describing derivation is for doc purposes only. * ---------------------------------------------------------------------------- * Added in FLE2v2: * @@ -54,38 +64,35 @@ * ServerCountAndContentionFactorEncryptionToken = * HMAC(ServerDerivedFromDataToken, 1) * ServerZerosEncryptionToken = HMAC(ServerDerivedFromDataToken, 2) + * ---------------------------------------------------------------------------- + * Added in Range V2: + * + * d is a 17-byte blob of zeros. + * + * AnchorPaddingTokenRoot = HMAC(ESCToken, d) + * Server-side: + * AnchorPaddingTokenKey = HMAC(AnchorPaddingTokenRoot, 1) + * AnchorPaddingTokenValue = HMAC(AnchorPaddingTokenRoot, 2) * ======================== End: FLE 2 Token Reference ======================== */ -// TODO: replace `CONCAT` with `BSON_CONCAT` after libbson dependency is -// upgraded to 1.20.0 or higher. -#ifndef CONCAT -#define CONCAT_1(a, b) a##b -#define CONCAT(a, b) CONCAT_1(a, b) -#endif -// TODO: replace `CONCAT3` with `BSON_CONCAT3` after libbson dependency is -// upgraded to 1.20.0 or higher. -#ifndef CONCAT3 -#define CONCAT3(a, b, c) CONCAT(a, CONCAT(b, c)) -#endif - /// Declare a token type named 'Name', with constructor parameters given by the /// remaining arguments. Each constructor will also have the implicit first /// argument '_mongocrypt_crypto_t* crypto' and a final argument /// 'mongocrypt_status_t* status' -#define DECL_TOKEN_TYPE(Name, ...) DECL_TOKEN_TYPE_1(Name, CONCAT(Name, _t), __VA_ARGS__) +#define DECL_TOKEN_TYPE(Name, ...) DECL_TOKEN_TYPE_1(Name, BSON_CONCAT(Name, _t), __VA_ARGS__) #define DECL_TOKEN_TYPE_1(Prefix, T, ...) \ /* Opaque typedef the struct */ \ typedef struct T T; \ /* Data-getter */ \ - extern const _mongocrypt_buffer_t *CONCAT(Prefix, _get)(const T *t); \ + extern const _mongocrypt_buffer_t *BSON_CONCAT(Prefix, _get)(const T *t); \ /* Destructor */ \ - extern void CONCAT(Prefix, _destroy)(T * t); \ + extern void BSON_CONCAT(Prefix, _destroy)(T * t); \ /* Constructor for server to create tokens from raw buffer */ \ - extern T *CONCAT(Prefix, _new_from_buffer)(_mongocrypt_buffer_t * buf); \ + extern T *BSON_CONCAT(Prefix, _new_from_buffer)(_mongocrypt_buffer_t * buf); \ /* Constructor. Parameter list given as variadic args */ \ - extern T *CONCAT(Prefix, _new)(_mongocrypt_crypto_t * crypto, __VA_ARGS__, mongocrypt_status_t * status) + extern T *BSON_CONCAT(Prefix, _new)(_mongocrypt_crypto_t * crypto, __VA_ARGS__, mongocrypt_status_t * status) DECL_TOKEN_TYPE(mc_CollectionsLevel1Token, const _mongocrypt_buffer_t *); DECL_TOKEN_TYPE(mc_ServerTokenDerivationLevel1Token, const _mongocrypt_buffer_t *); @@ -100,16 +107,23 @@ DECL_TOKEN_TYPE(mc_EDCDerivedFromDataToken, const mc_EDCToken_t *EDCToken, const DECL_TOKEN_TYPE(mc_ECCDerivedFromDataToken, const mc_ECCToken_t *ECCToken, const _mongocrypt_buffer_t *v); DECL_TOKEN_TYPE(mc_ESCDerivedFromDataToken, const mc_ESCToken_t *ESCToken, const _mongocrypt_buffer_t *v); -DECL_TOKEN_TYPE(mc_EDCDerivedFromDataTokenAndCounter, +DECL_TOKEN_TYPE(mc_EDCDerivedFromDataTokenAndContentionFactor, const mc_EDCDerivedFromDataToken_t *EDCDerivedFromDataToken, uint64_t u); -DECL_TOKEN_TYPE(mc_ESCDerivedFromDataTokenAndCounter, +DECL_TOKEN_TYPE(mc_ESCDerivedFromDataTokenAndContentionFactor, const mc_ESCDerivedFromDataToken_t *ESCDerivedFromDataToken, uint64_t u); -DECL_TOKEN_TYPE(mc_ECCDerivedFromDataTokenAndCounter, +DECL_TOKEN_TYPE(mc_ECCDerivedFromDataTokenAndContentionFactor, const mc_ECCDerivedFromDataToken_t *ECCDerivedFromDataToken, uint64_t u); +DECL_TOKEN_TYPE(mc_EDCTwiceDerivedToken, + const mc_EDCDerivedFromDataTokenAndContentionFactor_t *EDCDerivedFromDataTokenAndContentionFactor); +DECL_TOKEN_TYPE(mc_ESCTwiceDerivedTagToken, + const mc_ESCDerivedFromDataTokenAndContentionFactor_t *ESCDerivedFromDataTokenAndContentionFactor); +DECL_TOKEN_TYPE(mc_ESCTwiceDerivedValueToken, + const mc_ESCDerivedFromDataTokenAndContentionFactor_t *ESCDerivedFromDataTokenAndContentionFactor); + DECL_TOKEN_TYPE(mc_ServerDerivedFromDataToken, const mc_ServerTokenDerivationLevel1Token_t *ServerTokenDerivationToken, const _mongocrypt_buffer_t *v); @@ -118,6 +132,8 @@ DECL_TOKEN_TYPE(mc_ServerCountAndContentionFactorEncryptionToken, const mc_ServerDerivedFromDataToken_t *serverDerivedFromDataToken); DECL_TOKEN_TYPE(mc_ServerZerosEncryptionToken, const mc_ServerDerivedFromDataToken_t *serverDerivedFromDataToken); +DECL_TOKEN_TYPE(mc_AnchorPaddingTokenRoot, const mc_ESCToken_t *ESCToken); + #undef DECL_TOKEN_TYPE #undef DECL_TOKEN_TYPE_1 diff --git a/ext/libmongocrypt/libmongocrypt/src/mc-tokens.c b/ext/libmongocrypt/libmongocrypt/src/mc-tokens.c index 2b7afa3..34592dc 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mc-tokens.c +++ b/ext/libmongocrypt/libmongocrypt/src/mc-tokens.c @@ -15,12 +15,13 @@ */ #include "mc-tokens-private.h" +#include "mongocrypt-buffer-private.h" /// Define a token type of the given name, with constructor parameters given as /// the remaining arguments. This macro usage should be followed by the /// constructor body, with the implicit first argument '_mongocrypt_crypto_t* /// crypto' and final argument 'mongocrypt_status_t* status' -#define DEF_TOKEN_TYPE(Name, ...) DEF_TOKEN_TYPE_1(Name, CONCAT(Name, _t), __VA_ARGS__) +#define DEF_TOKEN_TYPE(Name, ...) DEF_TOKEN_TYPE_1(Name, BSON_CONCAT(Name, _t), __VA_ARGS__) #define DEF_TOKEN_TYPE_1(Prefix, T, ...) \ /* Define the struct for the token */ \ @@ -28,9 +29,9 @@ _mongocrypt_buffer_t data; \ }; \ /* Data-getter */ \ - const _mongocrypt_buffer_t *CONCAT(Prefix, _get)(const T *self) { return &self->data; } \ + const _mongocrypt_buffer_t *BSON_CONCAT(Prefix, _get)(const T *self) { return &self->data; } \ /* Destructor */ \ - void CONCAT(Prefix, _destroy)(T * self) { \ + void BSON_CONCAT(Prefix, _destroy)(T * self) { \ if (!self) { \ return; \ } \ @@ -38,23 +39,23 @@ bson_free(self); \ } \ /* Constructor. From raw buffer */ \ - T *CONCAT(Prefix, _new_from_buffer)(_mongocrypt_buffer_t * buf) { \ + T *BSON_CONCAT(Prefix, _new_from_buffer)(_mongocrypt_buffer_t * buf) { \ BSON_ASSERT(buf->len == MONGOCRYPT_HMAC_SHA256_LEN); \ T *t = bson_malloc(sizeof(T)); \ _mongocrypt_buffer_set_to(buf, &t->data); \ return t; \ } \ /* Constructor. Parameter list given as variadic args. */ \ - T *CONCAT(Prefix, _new)(_mongocrypt_crypto_t * crypto, __VA_ARGS__, mongocrypt_status_t * status) + T *BSON_CONCAT(Prefix, _new)(_mongocrypt_crypto_t * crypto, __VA_ARGS__, mongocrypt_status_t * status) #define IMPL_TOKEN_NEW_1(Name, Key, Arg, Clean) \ { \ - CONCAT(Name, _t) *t = bson_malloc(sizeof(CONCAT(Name, _t))); \ + BSON_CONCAT(Name, _t) *t = bson_malloc(sizeof(BSON_CONCAT(Name, _t))); \ _mongocrypt_buffer_init(&t->data); \ _mongocrypt_buffer_resize(&t->data, MONGOCRYPT_HMAC_SHA256_LEN); \ \ if (!_mongocrypt_hmac_sha_256(crypto, Key, Arg, &t->data, status)) { \ - CONCAT(Name, _destroy)(t); \ + BSON_CONCAT(Name, _destroy)(t); \ Clean; \ return NULL; \ } \ @@ -97,23 +98,46 @@ IMPL_TOKEN_NEW(mc_ESCDerivedFromDataToken, mc_ESCToken_get(ESCToken), v) DEF_TOKEN_TYPE(mc_ECCDerivedFromDataToken, const mc_ECCToken_t *ECCToken, const _mongocrypt_buffer_t *v) IMPL_TOKEN_NEW(mc_ECCDerivedFromDataToken, mc_ECCToken_get(ECCToken), v) +DEF_TOKEN_TYPE(mc_EDCTwiceDerivedToken, + const mc_EDCDerivedFromDataTokenAndContentionFactor_t *EDCDerivedFromDataTokenAndContentionFactor) +IMPL_TOKEN_NEW_CONST(mc_EDCTwiceDerivedToken, + mc_EDCDerivedFromDataTokenAndContentionFactor_get(EDCDerivedFromDataTokenAndContentionFactor), + 1) + +DEF_TOKEN_TYPE(mc_ESCTwiceDerivedTagToken, + const mc_ESCDerivedFromDataTokenAndContentionFactor_t *ESCDerivedFromDataTokenAndContentionFactor) +IMPL_TOKEN_NEW_CONST(mc_ESCTwiceDerivedTagToken, + mc_ESCDerivedFromDataTokenAndContentionFactor_get(ESCDerivedFromDataTokenAndContentionFactor), + 1) +DEF_TOKEN_TYPE(mc_ESCTwiceDerivedValueToken, + const mc_ESCDerivedFromDataTokenAndContentionFactor_t *ESCDerivedFromDataTokenAndContentionFactor) +IMPL_TOKEN_NEW_CONST(mc_ESCTwiceDerivedValueToken, + mc_ESCDerivedFromDataTokenAndContentionFactor_get(ESCDerivedFromDataTokenAndContentionFactor), + 2) + DEF_TOKEN_TYPE(mc_ServerDataEncryptionLevel1Token, const _mongocrypt_buffer_t *RootKey) IMPL_TOKEN_NEW_CONST(mc_ServerDataEncryptionLevel1Token, RootKey, 3) -DEF_TOKEN_TYPE(mc_EDCDerivedFromDataTokenAndCounter, +DEF_TOKEN_TYPE(mc_EDCDerivedFromDataTokenAndContentionFactor, const mc_EDCDerivedFromDataToken_t *EDCDerivedFromDataToken, uint64_t u) -IMPL_TOKEN_NEW_CONST(mc_EDCDerivedFromDataTokenAndCounter, mc_EDCDerivedFromDataToken_get(EDCDerivedFromDataToken), u) +IMPL_TOKEN_NEW_CONST(mc_EDCDerivedFromDataTokenAndContentionFactor, + mc_EDCDerivedFromDataToken_get(EDCDerivedFromDataToken), + u) -DEF_TOKEN_TYPE(mc_ESCDerivedFromDataTokenAndCounter, +DEF_TOKEN_TYPE(mc_ESCDerivedFromDataTokenAndContentionFactor, const mc_ESCDerivedFromDataToken_t *ESCDerivedFromDataToken, uint64_t u) -IMPL_TOKEN_NEW_CONST(mc_ESCDerivedFromDataTokenAndCounter, mc_ESCDerivedFromDataToken_get(ESCDerivedFromDataToken), u) +IMPL_TOKEN_NEW_CONST(mc_ESCDerivedFromDataTokenAndContentionFactor, + mc_ESCDerivedFromDataToken_get(ESCDerivedFromDataToken), + u) -DEF_TOKEN_TYPE(mc_ECCDerivedFromDataTokenAndCounter, +DEF_TOKEN_TYPE(mc_ECCDerivedFromDataTokenAndContentionFactor, const mc_ECCDerivedFromDataToken_t *ECCDerivedFromDataToken, uint64_t u) -IMPL_TOKEN_NEW_CONST(mc_ECCDerivedFromDataTokenAndCounter, mc_ECCDerivedFromDataToken_get(ECCDerivedFromDataToken), u) +IMPL_TOKEN_NEW_CONST(mc_ECCDerivedFromDataTokenAndContentionFactor, + mc_ECCDerivedFromDataToken_get(ECCDerivedFromDataToken), + u) /* FLE2v2 */ @@ -133,3 +157,23 @@ IMPL_TOKEN_NEW_CONST(mc_ServerCountAndContentionFactorEncryptionToken, DEF_TOKEN_TYPE(mc_ServerZerosEncryptionToken, const mc_ServerDerivedFromDataToken_t *serverDerivedFromDataToken) IMPL_TOKEN_NEW_CONST(mc_ServerZerosEncryptionToken, mc_ServerDerivedFromDataToken_get(serverDerivedFromDataToken), 2) + +// d = 17 bytes of 0, AnchorPaddingTokenRoot = HMAC(ESCToken, d) +#define ANCHOR_PADDING_TOKEN_D_LENGTH 17 +const uint8_t mc_AnchorPaddingTokenDValue[ANCHOR_PADDING_TOKEN_D_LENGTH] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +DEF_TOKEN_TYPE(mc_AnchorPaddingTokenRoot, const mc_ESCToken_t *ESCToken) { + _mongocrypt_buffer_t to_hash; + if (!_mongocrypt_buffer_copy_from_data_and_size(&to_hash, + mc_AnchorPaddingTokenDValue, + ANCHOR_PADDING_TOKEN_D_LENGTH)) { + return NULL; + } + IMPL_TOKEN_NEW_1(mc_AnchorPaddingTokenRoot, + mc_ESCToken_get(ESCToken), + &to_hash, + _mongocrypt_buffer_cleanup(&to_hash)) +} + +#undef ANCHOR_PADDING_TOKEN_D_LENGTH diff --git a/ext/libmongocrypt/libmongocrypt/src/mlib/int128.h b/ext/libmongocrypt/libmongocrypt/src/mlib/int128.h index 1619d20..d433383 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mlib/int128.h +++ b/ext/libmongocrypt/libmongocrypt/src/mlib/int128.h @@ -200,6 +200,13 @@ static mlib_constexpr_fn mlib_int128 mlib_int128_bitor(mlib_int128 l, mlib_int12 return MLIB_INIT(mlib_int128) MLIB_INT128_FROM_PARTS(l.r.lo | r.r.lo, l.r.hi | r.r.hi); } +/** + * @brief Bitwise-and two 128-bit integers + */ +static mlib_constexpr_fn mlib_int128 mlib_int128_bitand(mlib_int128 l, mlib_int128 r) { + return MLIB_INIT(mlib_int128) MLIB_INT128_FROM_PARTS(l.r.lo & r.r.lo, l.r.hi & r.r.hi); +} + // Multiply two 64bit integers to get a 128-bit result without overflow static mlib_constexpr_fn mlib_int128 _mlibUnsignedMult128(uint64_t left, uint64_t right) { // Perform a Knuth 4.3.1M multiplication @@ -245,6 +252,16 @@ static mlib_constexpr_fn int _mlibCountLeadingZeros_u64(uint64_t bits) { return n; } +static mlib_constexpr_fn int _mlibCountLeadingZeros_u128(mlib_int128 r) { + int clz_l = _mlibCountLeadingZeros_u64(r.r.hi); + if (clz_l != 64) { + return clz_l; + } + + int clz_r = _mlibCountLeadingZeros_u64(r.r.lo); + return clz_l + clz_r; +} + /// Implementation of Knuth's algorithm 4.3.1 D for unsigned integer division static mlib_constexpr_fn void _mlibKnuth431D(uint32_t *const u, const int ulen, const uint32_t *const v, const int vlen, uint32_t *quotient) { diff --git a/ext/libmongocrypt/libmongocrypt/src/mlib/int128.test.cpp b/ext/libmongocrypt/libmongocrypt/src/mlib/int128.test.cpp index 99e66d2..3a0854a 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mlib/int128.test.cpp +++ b/ext/libmongocrypt/libmongocrypt/src/mlib/int128.test.cpp @@ -14,6 +14,11 @@ // Old GCC and old MSVC have partially-broken constexpr that prevents us from // properly using static_assert with from_string() #define BROKEN_CONSTEXPR +#elif (defined(_MSC_VER) && _MSC_VER >= 1930) +// Avoid internal compiler error on VS 2022 versions 17.0 and newer when +// evaluating mlib_int128_from_string via operator""_i128. Assumed to be related +// to: https://developercommunity.visualstudio.com/t/User-defined-literals-cause-ICEs/10259122 +#define BROKEN_CONSTEXPR #endif #ifndef BROKEN_CONSTEXPR diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-binary-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-binary-private.h index 08da787..235caf2 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-binary-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-binary-private.h @@ -21,11 +21,6 @@ #include "mongocrypt.h" -struct _mongocrypt_binary_t { - uint8_t *data; - uint32_t len; -}; - bool _mongocrypt_binary_to_bson(mongocrypt_binary_t *binary, bson_t *out) MONGOCRYPT_WARN_UNUSED_RESULT; #endif /* MONGOCRYPT_BINARY_PRIVATE_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-buffer.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-buffer.c index f957915..cf7b1cc 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-buffer.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-buffer.c @@ -19,6 +19,11 @@ #include "mongocrypt-util-private.h" #include +// Require libbson 1.16.0 or newer. Fix for CDRIVER-3360 is needed. +#if !BSON_CHECK_VERSION(1, 16, 0) +#error "libbson 1.16.0 or newer is required." +#endif + #define INT32_LEN 4 #define TYPE_LEN 1 #define NULL_BYTE_LEN 1 @@ -306,13 +311,6 @@ bool _mongocrypt_buffer_to_bson_value(_mongocrypt_buffer_t *plaintext, uint8_t t } bson_value_copy(bson_iter_value(&iter), out); - /* Due to an open libbson bug (CDRIVER-3340), give an empty - * binary payload a real address. TODO: remove this after - * CDRIVER-3340 is fixed. */ - if (out->value_type == BSON_TYPE_BINARY && 0 == out->value.v_binary.data_len) { - out->value.v_binary.data = bson_malloc(1); /* Freed in bson_value_destroy */ - } - ret = true; fail: bson_free(data); diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key.c index 601ebdf..68deb6b 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key.c @@ -85,6 +85,7 @@ static void _dump_attr(void *attr_in) { for (altname = attr->alt_names; NULL != altname; altname = altname->next) { printf("%s\n", _mongocrypt_key_alt_name_get_string(altname)); } + bson_free(hex); } _mongocrypt_cache_key_value_t *_mongocrypt_cache_key_value_new(_mongocrypt_key_doc_t *key_doc, diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth-private.h index b15e2c8..7a52ea5 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth-private.h @@ -20,21 +20,19 @@ #include "mongocrypt-mutex-private.h" #include "mongocrypt-status-private.h" -typedef struct { - bson_t *entry; - char *access_token; - int64_t expiration_time_us; - mongocrypt_mutex_t mutex; /* global lock of cache. */ -} _mongocrypt_cache_oauth_t; - -_mongocrypt_cache_oauth_t *_mongocrypt_cache_oauth_new(void); - -void _mongocrypt_cache_oauth_destroy(_mongocrypt_cache_oauth_t *cache); - -bool _mongocrypt_cache_oauth_add(_mongocrypt_cache_oauth_t *cache, bson_t *oauth_response, mongocrypt_status_t *status); - -/* Returns a copy of the base64 encoded oauth token, or NULL if nothing is - * cached. */ -char *_mongocrypt_cache_oauth_get(_mongocrypt_cache_oauth_t *cache); - -#endif /* MONGOCRYPT_CACHE_OAUTH_PRIVATE_H */ \ No newline at end of file +// `mc_mapof_kmsid_to_token_t` maps a KMS ID (e.g. `azure` or `azure:myname`) to an OAuth token. +typedef struct _mc_mapof_kmsid_to_token_t mc_mapof_kmsid_to_token_t; + +mc_mapof_kmsid_to_token_t *mc_mapof_kmsid_to_token_new(void); +void mc_mapof_kmsid_to_token_destroy(mc_mapof_kmsid_to_token_t *k2t); +// `mc_mapof_kmsid_to_token_get_token` returns a copy of the base64 encoded oauth token, or NULL. +// Thread-safe. +char *mc_mapof_kmsid_to_token_get_token(mc_mapof_kmsid_to_token_t *k2t, const char *kmsid); +// `mc_mapof_kmsid_to_token_add_response` overwrites an entry if `kms_id` exists. +// Thread-safe. +bool mc_mapof_kmsid_to_token_add_response(mc_mapof_kmsid_to_token_t *k2t, + const char *kmsid, + bson_t *response, + mongocrypt_status_t *status); + +#endif /* MONGOCRYPT_CACHE_OAUTH_PRIVATE_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth.c index e11d222..9626e37 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth.c @@ -16,6 +16,7 @@ #include "mongocrypt-cache-oauth-private.h" +#include "mc-array-private.h" #include "mongocrypt-private.h" /* How long before the reported "expires_in" time cache entries get evicted. @@ -24,91 +25,119 @@ */ #define MONGOCRYPT_OAUTH_CACHE_EVICTION_PERIOD_US 5000 * 1000 -_mongocrypt_cache_oauth_t *_mongocrypt_cache_oauth_new(void) { - _mongocrypt_cache_oauth_t *cache; - - cache = bson_malloc0(sizeof(_mongocrypt_cache_oauth_t)); - _mongocrypt_mutex_init(&cache->mutex); - return cache; -} - -void _mongocrypt_cache_oauth_destroy(_mongocrypt_cache_oauth_t *cache) { - BSON_ASSERT_PARAM(cache); - - _mongocrypt_mutex_cleanup(&cache->mutex); - bson_destroy(cache->entry); - bson_free(cache->access_token); - bson_free(cache); -} - -bool _mongocrypt_cache_oauth_add(_mongocrypt_cache_oauth_t *cache, - bson_t *oauth_response, - mongocrypt_status_t *status) { - bson_iter_t iter; +typedef struct { + char *kmsid; + char *access_token; int64_t expiration_time_us; - int64_t cache_time_us; - int64_t expires_in_s; - int64_t expires_in_us; - const char *access_token; - - BSON_ASSERT_PARAM(cache); - BSON_ASSERT_PARAM(oauth_response); +} mc_mapof_kmsid_to_token_entry_t; + +struct _mc_mapof_kmsid_to_token_t { + mc_array_t entries; + mongocrypt_mutex_t mutex; // Guards `entries`. +}; + +mc_mapof_kmsid_to_token_t *mc_mapof_kmsid_to_token_new(void) { + mc_mapof_kmsid_to_token_t *k2t = bson_malloc0(sizeof(mc_mapof_kmsid_to_token_t)); + _mc_array_init(&k2t->entries, sizeof(mc_mapof_kmsid_to_token_entry_t)); + _mongocrypt_mutex_init(&k2t->mutex); + return k2t; +} - /* The OAuth spec strongly implies that the value of expires_in is positive, - * so the overflow checks in this function don't consider negative values. */ - if (!bson_iter_init_find(&iter, oauth_response, "expires_in") || !BSON_ITER_HOLDS_INT(&iter)) { - CLIENT_ERR("OAuth response invalid, no 'expires_in' field."); - return false; - } - cache_time_us = bson_get_monotonic_time(); - expires_in_s = bson_iter_as_int64(&iter); - BSON_ASSERT(expires_in_s <= INT64_MAX / 1000 / 1000); - expires_in_us = expires_in_s * 1000 * 1000; - BSON_ASSERT(expires_in_us <= INT64_MAX - cache_time_us - && expires_in_us + cache_time_us > MONGOCRYPT_OAUTH_CACHE_EVICTION_PERIOD_US); - expiration_time_us = expires_in_us + cache_time_us - MONGOCRYPT_OAUTH_CACHE_EVICTION_PERIOD_US; - - if (!bson_iter_init_find(&iter, oauth_response, "access_token") || !BSON_ITER_HOLDS_UTF8(&iter)) { - CLIENT_ERR("OAuth response invalid, no 'access_token' field."); - return false; +void mc_mapof_kmsid_to_token_destroy(mc_mapof_kmsid_to_token_t *k2t) { + if (!k2t) { + return; } - access_token = bson_iter_utf8(&iter, NULL); - - _mongocrypt_mutex_lock(&cache->mutex); - if (expiration_time_us > cache->expiration_time_us) { - bson_destroy(cache->entry); - cache->entry = bson_copy(oauth_response); - cache->expiration_time_us = expiration_time_us; - bson_free(cache->access_token); - cache->access_token = bson_strdup(access_token); + _mongocrypt_mutex_cleanup(&k2t->mutex); + for (size_t i = 0; i < k2t->entries.len; i++) { + mc_mapof_kmsid_to_token_entry_t k2te = _mc_array_index(&k2t->entries, mc_mapof_kmsid_to_token_entry_t, i); + bson_free(k2te.kmsid); + bson_free(k2te.access_token); } - _mongocrypt_mutex_unlock(&cache->mutex); - return true; + _mc_array_destroy(&k2t->entries); + bson_free(k2t); } -/* Returns a copy of the base64 encoded oauth token, or NULL if nothing is - * cached. */ -char *_mongocrypt_cache_oauth_get(_mongocrypt_cache_oauth_t *cache) { - char *access_token; +char *mc_mapof_kmsid_to_token_get_token(mc_mapof_kmsid_to_token_t *k2t, const char *kmsid) { + BSON_ASSERT_PARAM(k2t); + BSON_ASSERT_PARAM(kmsid); + + _mongocrypt_mutex_lock(&k2t->mutex); + + for (size_t i = 0; i < k2t->entries.len; i++) { + mc_mapof_kmsid_to_token_entry_t k2te = _mc_array_index(&k2t->entries, mc_mapof_kmsid_to_token_entry_t, i); + if (0 == strcmp(k2te.kmsid, kmsid)) { + if (bson_get_monotonic_time() >= k2te.expiration_time_us) { + // Expired. + _mongocrypt_mutex_unlock(&k2t->mutex); + return NULL; + } + char *access_token = bson_strdup(k2te.access_token); + _mongocrypt_mutex_unlock(&k2t->mutex); + return access_token; + } + } - BSON_ASSERT_PARAM(cache); + _mongocrypt_mutex_unlock(&k2t->mutex); + return NULL; +} - _mongocrypt_mutex_lock(&cache->mutex); - if (!cache->entry) { - _mongocrypt_mutex_unlock(&cache->mutex); - return NULL; - } +bool mc_mapof_kmsid_to_token_add_response(mc_mapof_kmsid_to_token_t *k2t, + const char *kmsid, + bson_t *response, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(k2t); + BSON_ASSERT_PARAM(kmsid); + BSON_ASSERT_PARAM(response); - if (bson_get_monotonic_time() >= cache->expiration_time_us) { - bson_destroy(cache->entry); - cache->entry = NULL; - cache->expiration_time_us = 0; - _mongocrypt_mutex_unlock(&cache->mutex); - return NULL; + // Parse access token before locking. + const char *access_token; + int64_t expiration_time_us; + { + bson_iter_t iter; + int64_t cache_time_us; + int64_t expires_in_s; + int64_t expires_in_us; + + /* The OAuth spec strongly implies that the value of expires_in is positive, + * so the overflow checks in this function don't consider negative values. */ + if (!bson_iter_init_find(&iter, response, "expires_in") || !BSON_ITER_HOLDS_INT(&iter)) { + CLIENT_ERR("OAuth response invalid, no 'expires_in' field."); + return false; + } + cache_time_us = bson_get_monotonic_time(); + expires_in_s = bson_iter_as_int64(&iter); + BSON_ASSERT(expires_in_s <= INT64_MAX / 1000 / 1000); + expires_in_us = expires_in_s * 1000 * 1000; + BSON_ASSERT(expires_in_us <= INT64_MAX - cache_time_us + && expires_in_us + cache_time_us > MONGOCRYPT_OAUTH_CACHE_EVICTION_PERIOD_US); + expiration_time_us = expires_in_us + cache_time_us - MONGOCRYPT_OAUTH_CACHE_EVICTION_PERIOD_US; + + if (!bson_iter_init_find(&iter, response, "access_token") || !BSON_ITER_HOLDS_UTF8(&iter)) { + CLIENT_ERR("OAuth response invalid, no 'access_token' field."); + return false; + } + access_token = bson_iter_utf8(&iter, NULL); } - access_token = bson_strdup(cache->access_token); - _mongocrypt_mutex_unlock(&cache->mutex); - - return access_token; + _mongocrypt_mutex_lock(&k2t->mutex); + + // Check if there is an existing entry. + for (size_t i = 0; i < k2t->entries.len; i++) { + mc_mapof_kmsid_to_token_entry_t *k2te = &_mc_array_index(&k2t->entries, mc_mapof_kmsid_to_token_entry_t, i); + if (0 == strcmp(k2te->kmsid, kmsid)) { + // Update entry. + bson_free(k2te->access_token); + k2te->access_token = bson_strdup(access_token); + k2te->expiration_time_us = expiration_time_us; + _mongocrypt_mutex_unlock(&k2t->mutex); + return true; + } + } + // Create an entry. + mc_mapof_kmsid_to_token_entry_t to_put = {.kmsid = bson_strdup(kmsid), + .access_token = bson_strdup(access_token), + .expiration_time_us = expiration_time_us}; + _mc_array_append_val(&k2t->entries, to_put); + _mongocrypt_mutex_unlock(&k2t->mutex); + return true; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-crypto.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-crypto.c index 5682ad5..2d2a4c4 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-crypto.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-crypto.c @@ -78,7 +78,10 @@ static bool _crypto_aes_256_ctr_encrypt_decrypt_via_ecb(void *ctx, /* XOR resulting stream with original data */ for (uint32_t i = 0; i < bytes_written && ptr < args.in->len; i++, ptr++) { - out_bin.data[ptr] = in_bin.data[ptr] ^ tmp_bin.data[i]; + uint8_t *in_bin_u8 = in_bin.data; + uint8_t *out_bin_u8 = out_bin.data; + uint8_t *tmp_bin_u8 = tmp_bin.data; + out_bin_u8[ptr] = in_bin_u8[ptr] ^ tmp_bin_u8[i]; } /* Increment value in CTR buffer */ @@ -86,9 +89,10 @@ static bool _crypto_aes_256_ctr_encrypt_decrypt_via_ecb(void *ctx, /* assert rather than return since this should never happen */ BSON_ASSERT(ctr_bin.len == 0u || ctr_bin.len - 1u <= INT_MAX); for (int i = (int)ctr_bin.len - 1; i >= 0 && carry != 0; --i) { - uint32_t bpp = carry + ctr_bin.data[i]; + uint8_t *ctr_bin_u8 = ctr_bin.data; + uint32_t bpp = carry + ctr_bin_u8[i]; carry = bpp >> 8; - ctr_bin.data[i] = bpp & 0xFF; + ctr_bin_u8[i] = bpp & 0xFF; } } @@ -1384,6 +1388,8 @@ bool _mongocrypt_random_uint64(_mongocrypt_crypto_t *crypto, } memcpy(&rand_u64, rand_u64_buf.data, rand_u64_buf.len); + // Use little-endian to enable deterministic tests on big-endian machines. + rand_u64 = BSON_UINT64_FROM_LE(rand_u64); if (rand_u64 >= min) { break; diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c index 2b98957..4bb08ed 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c @@ -16,6 +16,7 @@ #include "mongocrypt-crypto-private.h" #include "mongocrypt-ctx-private.h" +#include "mongocrypt-kms-ctx-private.h" #include "mongocrypt-private.h" #include "mongocrypt.h" @@ -46,107 +47,161 @@ static mongocrypt_kms_ctx_t *_next_kms_ctx(mongocrypt_ctx_t *ctx) { return &dkctx->kms; } -static bool _kms_kmip_start(mongocrypt_ctx_t *ctx) { +static bool _kms_kmip_start(mongocrypt_ctx_t *ctx, const mc_kms_creds_t *kc) { bool ret = false; _mongocrypt_ctx_datakey_t *dkctx = (_mongocrypt_ctx_datakey_t *)ctx; char *user_supplied_keyid = NULL; - _mongocrypt_endpoint_t *endpoint = NULL; + const _mongocrypt_endpoint_t *endpoint = NULL; mongocrypt_status_t *status = ctx->status; _mongocrypt_buffer_t secretdata = {0}; BSON_ASSERT_PARAM(ctx); + BSON_ASSERT_PARAM(kc); + BSON_ASSERT(kc->type == MONGOCRYPT_KMS_PROVIDER_KMIP); if (ctx->opts.kek.kms_provider != MONGOCRYPT_KMS_PROVIDER_KMIP) { CLIENT_ERR("KMS provider is not KMIP"); goto fail; } + const bool delegated = ctx->opts.kek.provider.kmip.delegated; user_supplied_keyid = ctx->opts.kek.provider.kmip.key_id; if (ctx->opts.kek.provider.kmip.endpoint) { endpoint = ctx->opts.kek.provider.kmip.endpoint; - } else if (_mongocrypt_ctx_kms_providers(ctx)->kmip.endpoint) { - endpoint = _mongocrypt_ctx_kms_providers(ctx)->kmip.endpoint; + } else if (kc->value.kmip.endpoint) { + endpoint = kc->value.kmip.endpoint; } else { CLIENT_ERR("endpoint not set for KMIP request"); goto fail; } - /* The KMIP createDataKey flow is the following: - * - * 1. Send a KMIP Register request with a new 96 byte key as a SecretData - * managed object. This returns a Unique Identifier. - * 2. Send a KMIP Activate request with the Unique Identifier. - * This returns the same Unique Identifier. - * 3. Send a KMIP Get request with the Unique Identifier. - * This returns the 96 byte SecretData. - * 4. Use the 96 byte SecretData to encrypt a new DEK. - * - * If the user set a 'keyId' to use, the flow begins at step 3. - */ - if (user_supplied_keyid && !dkctx->kmip_unique_identifier) { /* User set a 'keyId'. */ dkctx->kmip_unique_identifier = bson_strdup(user_supplied_keyid); dkctx->kmip_activated = true; - /* Fall through to Step 3. */ } - if (!dkctx->kmip_unique_identifier) { - /* User did not set a 'keyId'. */ - /* Step 1. Send a KMIP Register request with a new 96 byte SecretData. */ - _mongocrypt_buffer_init(&secretdata); - _mongocrypt_buffer_resize(&secretdata, MONGOCRYPT_KEY_LEN); - if (!_mongocrypt_random(ctx->crypt->crypto, &secretdata, MONGOCRYPT_KEY_LEN, ctx->status)) { - goto fail; + if (delegated) { + /* + * The KMIP delegated createDataKey flow is the following: + * 1. Send a KMIP Create request (symmetric key) (returns keyId) + * 2. Send a KMIP Activate request with that keyId + * 3. Send a KMIP Encrypt request to encrypt the DEK + * + * Steps 1 and 2 are skipped if the user provided a keyId + */ + + if (!dkctx->kmip_unique_identifier) { + /* User did not set a 'keyId'. */ + /* Step 1. Send a KMIP Create request for a new AES-256 symmetric key. */ + if (!_mongocrypt_kms_ctx_init_kmip_create(&dkctx->kms, endpoint, ctx->opts.kek.kmsid, &ctx->crypt->log)) { + mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); + goto fail; + } + ctx->state = MONGOCRYPT_CTX_NEED_KMS; + goto success; } - if (!_mongocrypt_kms_ctx_init_kmip_register(&dkctx->kms, - endpoint, - secretdata.data, - secretdata.len, - &ctx->crypt->log)) { - mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); - goto fail; + if (!dkctx->kmip_activated) { + /* Step 2. Send a KMIP Activate request. */ + if (!_mongocrypt_kms_ctx_init_kmip_activate(&dkctx->kms, + endpoint, + dkctx->kmip_unique_identifier, + ctx->opts.kek.kmsid, + &ctx->crypt->log)) { + mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); + goto fail; + } + ctx->state = MONGOCRYPT_CTX_NEED_KMS; + goto success; } - ctx->state = MONGOCRYPT_CTX_NEED_KMS; - goto success; - } + if (!dkctx->encrypted_key_material.data) { + /* Step 3. Have the KMS encrypt a new DEK. */ + if (!_mongocrypt_kms_ctx_init_kmip_encrypt(&dkctx->kms, + endpoint, + dkctx->kmip_unique_identifier, + ctx->opts.kek.kmsid, + &dkctx->plaintext_key_material, + &ctx->crypt->log)) { + mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); + goto fail; + } + ctx->state = MONGOCRYPT_CTX_NEED_KMS; + goto success; + } + } else { + /* The KMIP createDataKey flow is the following: + * + * 1. Send a KMIP Register request with a new 96 byte key as a SecretData + * managed object. This returns a Unique Identifier. + * 2. Send a KMIP Activate request with the Unique Identifier. + * This returns the same Unique Identifier. + * 3. Send a KMIP Get request with the Unique Identifier. + * This returns the 96 byte SecretData. + * 4. Use the 96 byte SecretData to encrypt a new DEK. + * + * If the user set a 'keyId' to use, the flow begins at step 3. + */ + if (!dkctx->kmip_unique_identifier) { + /* User did not set a 'keyId'. */ + /* Step 1. Send a KMIP Register request with a new 96 byte SecretData. */ + _mongocrypt_buffer_init(&secretdata); + _mongocrypt_buffer_resize(&secretdata, MONGOCRYPT_KEY_LEN); + if (!_mongocrypt_random(ctx->crypt->crypto, &secretdata, MONGOCRYPT_KEY_LEN, ctx->status)) { + goto fail; + } - if (!dkctx->kmip_activated) { - /* Step 2. Send a KMIP Activate request. */ - if (!_mongocrypt_kms_ctx_init_kmip_activate(&dkctx->kms, - endpoint, - dkctx->kmip_unique_identifier, - &ctx->crypt->log)) { - mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); - goto fail; + if (!_mongocrypt_kms_ctx_init_kmip_register(&dkctx->kms, + endpoint, + secretdata.data, + secretdata.len, + ctx->opts.kek.kmsid, + &ctx->crypt->log)) { + mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); + goto fail; + } + ctx->state = MONGOCRYPT_CTX_NEED_KMS; + goto success; } - ctx->state = MONGOCRYPT_CTX_NEED_KMS; - goto success; - } - if (!dkctx->kmip_secretdata.data) { - /* Step 3. Send a KMIP Get request with the Unique Identifier. */ - if (!_mongocrypt_kms_ctx_init_kmip_get(&dkctx->kms, - endpoint, - dkctx->kmip_unique_identifier, - &ctx->crypt->log)) { - mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); - goto fail; + if (!dkctx->kmip_activated) { + /* Step 2. Send a KMIP Activate request. */ + if (!_mongocrypt_kms_ctx_init_kmip_activate(&dkctx->kms, + endpoint, + dkctx->kmip_unique_identifier, + ctx->opts.kek.kmsid, + &ctx->crypt->log)) { + mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); + goto fail; + } + ctx->state = MONGOCRYPT_CTX_NEED_KMS; + goto success; } - ctx->state = MONGOCRYPT_CTX_NEED_KMS; - goto success; - } - /* Step 4. Use the 96 byte SecretData to encrypt a new DEK. */ - if (!_mongocrypt_wrap_key(ctx->crypt->crypto, - &dkctx->kmip_secretdata, - &dkctx->plaintext_key_material, - &dkctx->encrypted_key_material, - ctx->status)) { - goto fail; + if (!dkctx->kmip_secretdata.data) { + /* Step 3. Send a KMIP Get request with the Unique Identifier. */ + if (!_mongocrypt_kms_ctx_init_kmip_get(&dkctx->kms, + endpoint, + dkctx->kmip_unique_identifier, + ctx->opts.kek.kmsid, + &ctx->crypt->log)) { + mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); + goto fail; + } + ctx->state = MONGOCRYPT_CTX_NEED_KMS; + goto success; + } + + /* Step 4. Use the 96 byte SecretData to encrypt a new DEK. */ + if (!_mongocrypt_wrap_key(ctx->crypt->crypto, + &dkctx->kmip_secretdata, + &dkctx->plaintext_key_material, + &dkctx->encrypted_key_material, + ctx->status)) { + goto fail; + } } if (!ctx->opts.kek.provider.kmip.key_id) { @@ -180,14 +235,23 @@ static bool _kms_start(mongocrypt_ctx_t *ctx) { dkctx = (_mongocrypt_ctx_datakey_t *)ctx; + mc_kms_creds_t kc; + if (!_mongocrypt_opts_kms_providers_lookup(kms_providers, ctx->opts.kek.kmsid, &kc)) { + mongocrypt_status_t *status = ctx->status; + CLIENT_ERR("KMS provider `%s` is not configured", ctx->opts.kek.kmsid); + _mongocrypt_ctx_fail(ctx); + goto done; + } + /* Clear out any pre-existing initialized KMS context, and zero it (so it is * safe to call cleanup again). */ _mongocrypt_kms_ctx_cleanup(&dkctx->kms); memset(&dkctx->kms, 0, sizeof(dkctx->kms)); dkctx->kms_returned = false; if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_LOCAL) { + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_LOCAL); if (!_mongocrypt_wrap_key(ctx->crypt->crypto, - &kms_providers->local.key, + &kc.value.local.key, &dkctx->plaintext_key_material, &dkctx->encrypted_key_material, ctx->status)) { @@ -203,8 +267,9 @@ static bool _kms_start(mongocrypt_ctx_t *ctx) { kms_providers, &ctx->opts, &dkctx->plaintext_key_material, - &ctx->crypt->log, - ctx->crypt->crypto)) { + ctx->crypt->crypto, + ctx->opts.kek.kmsid, + &ctx->crypt->log)) { mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); _mongocrypt_ctx_fail(ctx); goto done; @@ -212,27 +277,30 @@ static bool _kms_start(mongocrypt_ctx_t *ctx) { ctx->state = MONGOCRYPT_CTX_NEED_KMS; } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_AZURE) { - if (ctx->kms_providers.azure.access_token) { - access_token = bson_strdup(ctx->kms_providers.azure.access_token); + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_AZURE); + if (kc.value.azure.access_token) { + access_token = bson_strdup(kc.value.azure.access_token); } else { - access_token = _mongocrypt_cache_oauth_get(ctx->crypt->cache_oauth_azure); + access_token = mc_mapof_kmsid_to_token_get_token(ctx->crypt->cache_oauth, ctx->opts.kek.kmsid); } if (access_token) { if (!_mongocrypt_kms_ctx_init_azure_wrapkey(&dkctx->kms, - &ctx->crypt->log, kms_providers, &ctx->opts, access_token, - &dkctx->plaintext_key_material)) { + &dkctx->plaintext_key_material, + ctx->opts.kek.kmsid, + &ctx->crypt->log)) { mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); _mongocrypt_ctx_fail(ctx); goto done; } } else { if (!_mongocrypt_kms_ctx_init_azure_auth(&dkctx->kms, - &ctx->crypt->log, - kms_providers, - ctx->opts.kek.provider.azure.key_vault_endpoint)) { + &kc, + ctx->opts.kek.provider.azure.key_vault_endpoint, + ctx->opts.kek.kmsid, + &ctx->crypt->log)) { mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); _mongocrypt_ctx_fail(ctx); goto done; @@ -240,28 +308,31 @@ static bool _kms_start(mongocrypt_ctx_t *ctx) { } ctx->state = MONGOCRYPT_CTX_NEED_KMS; } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_GCP) { - if (NULL != ctx->kms_providers.gcp.access_token) { - access_token = bson_strdup((const char *)ctx->kms_providers.gcp.access_token); + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_GCP); + if (NULL != kc.value.gcp.access_token) { + access_token = bson_strdup(kc.value.gcp.access_token); } else { - access_token = _mongocrypt_cache_oauth_get(ctx->crypt->cache_oauth_gcp); + access_token = mc_mapof_kmsid_to_token_get_token(ctx->crypt->cache_oauth, ctx->opts.kek.kmsid); } if (access_token) { if (!_mongocrypt_kms_ctx_init_gcp_encrypt(&dkctx->kms, - &ctx->crypt->log, kms_providers, &ctx->opts, access_token, - &dkctx->plaintext_key_material)) { + &dkctx->plaintext_key_material, + ctx->opts.kek.kmsid, + &ctx->crypt->log)) { mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); _mongocrypt_ctx_fail(ctx); goto done; } } else { if (!_mongocrypt_kms_ctx_init_gcp_auth(&dkctx->kms, - &ctx->crypt->log, &ctx->crypt->opts, - kms_providers, - ctx->opts.kek.provider.gcp.endpoint)) { + &kc, + ctx->opts.kek.provider.gcp.endpoint, + ctx->opts.kek.kmsid, + &ctx->crypt->log)) { mongocrypt_kms_ctx_status(&dkctx->kms, ctx->status); _mongocrypt_ctx_fail(ctx); goto done; @@ -269,7 +340,7 @@ static bool _kms_start(mongocrypt_ctx_t *ctx) { } ctx->state = MONGOCRYPT_CTX_NEED_KMS; } else if (ctx->opts.kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_KMIP) { - if (!_kms_kmip_start(ctx)) { + if (!_kms_kmip_start(ctx, &kc)) { goto done; } } else { @@ -305,7 +376,10 @@ static bool _kms_done(mongocrypt_ctx_t *ctx) { bson_t oauth_response; BSON_ASSERT(_mongocrypt_buffer_to_bson(&dkctx->kms.result, &oauth_response)); - if (!_mongocrypt_cache_oauth_add(ctx->crypt->cache_oauth_azure, &oauth_response, status)) { + if (!mc_mapof_kmsid_to_token_add_response(ctx->crypt->cache_oauth, + ctx->opts.kek.kmsid, + &oauth_response, + status)) { return _mongocrypt_ctx_fail(ctx); } return _kms_start(ctx); @@ -313,11 +387,15 @@ static bool _kms_done(mongocrypt_ctx_t *ctx) { bson_t oauth_response; BSON_ASSERT(_mongocrypt_buffer_to_bson(&dkctx->kms.result, &oauth_response)); - if (!_mongocrypt_cache_oauth_add(ctx->crypt->cache_oauth_gcp, &oauth_response, status)) { + if (!mc_mapof_kmsid_to_token_add_response(ctx->crypt->cache_oauth, + ctx->opts.kek.kmsid, + &oauth_response, + status)) { return _mongocrypt_ctx_fail(ctx); } return _kms_start(ctx); - } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_REGISTER) { + } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_REGISTER + || dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_CREATE) { dkctx->kmip_unique_identifier = bson_strdup((const char *)dkctx->kms.result.data); return _kms_start(ctx); } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_ACTIVATE) { @@ -326,6 +404,9 @@ static bool _kms_done(mongocrypt_ctx_t *ctx) { } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_GET) { _mongocrypt_buffer_copy_to(&dkctx->kms.result, &dkctx->kmip_secretdata); return _kms_start(ctx); + } else if (dkctx->kms.req_type == MONGOCRYPT_KMS_KMIP_ENCRYPT) { + _mongocrypt_buffer_copy_to(&dkctx->kms.result, &dkctx->encrypted_key_material); + return _kms_start(ctx); } /* Store the result. */ @@ -475,7 +556,7 @@ bool mongocrypt_ctx_datakey_init(mongocrypt_ctx_t *ctx) { } } - if (_mongocrypt_needs_credentials_for_provider(ctx->crypt, ctx->opts.kek.kms_provider)) { + if (_mongocrypt_needs_credentials_for_provider(ctx->crypt, ctx->opts.kek.kms_provider, ctx->opts.kek.kmsid_name)) { ctx->state = MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS; } else if (!_kms_start(ctx)) { goto done; @@ -484,4 +565,4 @@ bool mongocrypt_ctx_datakey_init(mongocrypt_ctx_t *ctx) { ret = true; done: return ret; -} +} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-decrypt.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-decrypt.c index c37e51e..cd696b3 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-decrypt.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-decrypt.c @@ -406,7 +406,7 @@ static bool _replace_ciphertext_with_plaintext(void *ctx, static bool _finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { bson_t as_bson, final_bson; - bson_iter_t iter; + bson_iter_t iter = {0}; _mongocrypt_ctx_decrypt_t *dctx; bool res; @@ -504,6 +504,7 @@ static bool _collect_K_KeyID_from_FLE2IndexedEncryptedValueV2(void *ctx, || (in->data[0] == MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2)); mc_FLE2IndexedEncryptedValueV2_t *iev = mc_FLE2IndexedEncryptedValueV2_new(); + _mongocrypt_buffer_t S_Key = {0}; CHECK_AND_RETURN(iev); CHECK_AND_RETURN(mc_FLE2IndexedEncryptedValueV2_parse(iev, in, status)); @@ -511,7 +512,6 @@ static bool _collect_K_KeyID_from_FLE2IndexedEncryptedValueV2(void *ctx, CHECK_AND_RETURN(S_KeyId); _mongocrypt_key_broker_t *kb = ctx; - _mongocrypt_buffer_t S_Key = {0}; CHECK_AND_RETURN_KB_STATUS(_mongocrypt_key_broker_decrypted_key_by_id(kb, S_KeyId, &S_Key)); /* Decrypt InnerEncrypted to get K_KeyId. */ @@ -537,6 +537,7 @@ static bool _collect_K_KeyID_from_FLE2IndexedEncryptedValue(void *ctx, BSON_ASSERT_PARAM(in); BSON_ASSERT(in->data); bool ret = false; + _mongocrypt_buffer_t S_Key = {0}; BSON_ASSERT((in->data[0] == MC_SUBTYPE_FLE2IndexedEqualityEncryptedValue) || (in->data[0] == MC_SUBTYPE_FLE2IndexedRangeEncryptedValue)); @@ -549,7 +550,6 @@ static bool _collect_K_KeyID_from_FLE2IndexedEncryptedValue(void *ctx, CHECK_AND_RETURN(S_KeyId); _mongocrypt_key_broker_t *kb = ctx; - _mongocrypt_buffer_t S_Key = {0}; CHECK_AND_RETURN_KB_STATUS(_mongocrypt_key_broker_decrypted_key_by_id(kb, S_KeyId, &S_Key)); /* Decrypt InnerEncrypted to get K_KeyId. */ @@ -604,7 +604,7 @@ static bool _check_for_K_KeyId(mongocrypt_ctx_t *ctx) { } bson_t as_bson; - bson_iter_t iter; + bson_iter_t iter = {0}; _mongocrypt_ctx_decrypt_t *dctx = (_mongocrypt_ctx_decrypt_t *)ctx; if (!_mongocrypt_buffer_to_bson(&dctx->original_doc, &as_bson)) { return _mongocrypt_ctx_fail_w_msg(ctx, "error converting original_doc to bson"); @@ -843,7 +843,7 @@ static bool _kms_done(mongocrypt_ctx_t *ctx) { bool mongocrypt_ctx_decrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *doc) { _mongocrypt_ctx_decrypt_t *dctx; bson_t as_bson; - bson_iter_t iter; + bson_iter_t iter = {0}; _mongocrypt_ctx_opts_spec_t opts_spec; memset(&opts_spec, 0, sizeof(opts_spec)); diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c index cdfb4b5..f8c0c6d 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "mc-efc-private.h" #include "mc-fle2-rfds-private.h" #include "mc-tokens-private.h" #include "mongocrypt-ciphertext-private.h" @@ -23,6 +24,7 @@ #include "mongocrypt-marking-private.h" #include "mongocrypt-traverse-util-private.h" #include "mongocrypt-util-private.h" // mc_iter_document_as_bson +#include "mongocrypt.h" /* _fle2_append_encryptedFieldConfig copies encryptedFieldConfig and applies * default state collection names for escCollection, eccCollection, and @@ -30,7 +32,7 @@ static bool _fle2_append_encryptedFieldConfig(const mongocrypt_ctx_t *ctx, bson_t *dst, bson_t *encryptedFieldConfig, - const char *coll_name, + const char *target_coll, mongocrypt_status_t *status) { bson_iter_t iter; bool has_escCollection = false; @@ -39,7 +41,7 @@ static bool _fle2_append_encryptedFieldConfig(const mongocrypt_ctx_t *ctx, BSON_ASSERT_PARAM(dst); BSON_ASSERT_PARAM(encryptedFieldConfig); - BSON_ASSERT_PARAM(coll_name); + BSON_ASSERT_PARAM(target_coll); if (!bson_iter_init(&iter, encryptedFieldConfig)) { CLIENT_ERR("unable to iterate encryptedFieldConfig"); @@ -63,7 +65,7 @@ static bool _fle2_append_encryptedFieldConfig(const mongocrypt_ctx_t *ctx, } if (!has_escCollection) { - char *default_escCollection = bson_strdup_printf("enxcol_.%s.esc", coll_name); + char *default_escCollection = bson_strdup_printf("enxcol_.%s.esc", target_coll); if (!BSON_APPEND_UTF8(dst, "escCollection", default_escCollection)) { CLIENT_ERR("unable to append escCollection"); bson_free(default_escCollection); @@ -72,7 +74,7 @@ static bool _fle2_append_encryptedFieldConfig(const mongocrypt_ctx_t *ctx, bson_free(default_escCollection); } if (!has_eccCollection && !ctx->crypt->opts.use_fle2_v2) { - char *default_eccCollection = bson_strdup_printf("enxcol_.%s.ecc", coll_name); + char *default_eccCollection = bson_strdup_printf("enxcol_.%s.ecc", target_coll); if (!BSON_APPEND_UTF8(dst, "eccCollection", default_eccCollection)) { CLIENT_ERR("unable to append eccCollection"); bson_free(default_eccCollection); @@ -81,7 +83,7 @@ static bool _fle2_append_encryptedFieldConfig(const mongocrypt_ctx_t *ctx, bson_free(default_eccCollection); } if (!has_ecocCollection) { - char *default_ecocCollection = bson_strdup_printf("enxcol_.%s.ecoc", coll_name); + char *default_ecocCollection = bson_strdup_printf("enxcol_.%s.ecoc", target_coll); if (!BSON_APPEND_UTF8(dst, "ecocCollection", default_ecocCollection)) { CLIENT_ERR("unable to append ecocCollection"); bson_free(default_ecocCollection); @@ -94,20 +96,20 @@ static bool _fle2_append_encryptedFieldConfig(const mongocrypt_ctx_t *ctx, static bool _fle2_append_encryptionInformation(const mongocrypt_ctx_t *ctx, bson_t *dst, - const char *ns, + const char *target_ns, bson_t *encryptedFieldConfig, bson_t *deleteTokens, - const char *coll_name, + const char *target_coll, mongocrypt_status_t *status) { bson_t encryption_information_bson; bson_t schema_bson; bson_t encrypted_field_config_bson; BSON_ASSERT_PARAM(dst); - BSON_ASSERT_PARAM(ns); + BSON_ASSERT_PARAM(target_ns); BSON_ASSERT_PARAM(encryptedFieldConfig); /* deleteTokens may be NULL */ - BSON_ASSERT_PARAM(coll_name); + BSON_ASSERT_PARAM(target_coll); if (!BSON_APPEND_DOCUMENT_BEGIN(dst, "encryptionInformation", &encryption_information_bson)) { CLIENT_ERR("unable to begin appending 'encryptionInformation'"); @@ -122,7 +124,7 @@ static bool _fle2_append_encryptionInformation(const mongocrypt_ctx_t *ctx, return false; } - if (!BSON_APPEND_DOCUMENT_BEGIN(&schema_bson, ns, &encrypted_field_config_bson)) { + if (!BSON_APPEND_DOCUMENT_BEGIN(&schema_bson, target_ns, &encrypted_field_config_bson)) { CLIENT_ERR("unable to begin appending 'encryptedFieldConfig' to " "'encryptionInformation'.'schema'"); return false; @@ -131,7 +133,7 @@ static bool _fle2_append_encryptionInformation(const mongocrypt_ctx_t *ctx, if (!_fle2_append_encryptedFieldConfig(ctx, &encrypted_field_config_bson, encryptedFieldConfig, - coll_name, + target_coll, status)) { return false; } @@ -153,8 +155,8 @@ static bool _fle2_append_encryptionInformation(const mongocrypt_ctx_t *ctx, "'encryptionInformation'"); return false; } - if (!BSON_APPEND_DOCUMENT(&delete_tokens_bson, ns, deleteTokens)) { - CLIENT_ERR("unable to append '%s' to 'deleteTokens'", ns); + if (!BSON_APPEND_DOCUMENT(&delete_tokens_bson, target_ns, deleteTokens)) { + CLIENT_ERR("unable to append '%s' to 'deleteTokens'", target_ns); return false; } if (!bson_append_document_end(&encryption_information_bson, &delete_tokens_bson)) { @@ -178,12 +180,12 @@ typedef enum { MC_TO_CSFLE, MC_TO_MONGOCRYPTD, MC_TO_MONGOD } mc_cmd_target_t; * * @param cmd_name The name of the command. * @param cmd The command being rewritten. It is an input and output. - * @param ns The . namespace for the command. + * @param target_ns The . namespace for the command. * @param encryptedFieldConfig The "encryptedFields" document for the * collection. * @param deleteTokens Delete tokens to append to "encryptionInformation". May * be NULL. - * @param coll_name The collection name. + * @param target_coll The collection name. * @param cmd_target The intended destination of the command. csfle, * mongocryptd, and mongod have different requirements for the location of * "encryptionInformation". @@ -194,10 +196,10 @@ typedef enum { MC_TO_CSFLE, MC_TO_MONGOCRYPTD, MC_TO_MONGOD } mc_cmd_target_t; static bool _fle2_insert_encryptionInformation(const mongocrypt_ctx_t *ctx, const char *cmd_name, bson_t *cmd /* in and out */, - const char *ns, + const char *target_ns, bson_t *encryptedFieldConfig, bson_t *deleteTokens, - const char *coll_name, + const char *target_coll, mc_cmd_target_t cmd_target, mongocrypt_status_t *status) { bson_t out = BSON_INITIALIZER; @@ -207,16 +209,96 @@ static bool _fle2_insert_encryptionInformation(const mongocrypt_ctx_t *ctx, BSON_ASSERT_PARAM(cmd_name); BSON_ASSERT_PARAM(cmd); - BSON_ASSERT_PARAM(ns); + BSON_ASSERT_PARAM(target_ns); BSON_ASSERT_PARAM(encryptedFieldConfig); /* deleteTokens may be NULL */ - BSON_ASSERT_PARAM(coll_name); + BSON_ASSERT_PARAM(target_coll); + + // For `bulkWrite`, append `encryptionInformation` inside the `nsInfo.0` document. + if (0 == strcmp(cmd_name, "bulkWrite")) { + // Get the single `nsInfo` document from the input command. + bson_t nsInfo; // Non-owning. + { + bson_iter_t nsInfo_iter; + if (!bson_iter_init(&nsInfo_iter, cmd)) { + CLIENT_ERR("failed to iterate command"); + goto fail; + } + if (!bson_iter_find_descendant(&nsInfo_iter, "nsInfo.0", &nsInfo_iter)) { + CLIENT_ERR("expected one namespace in `bulkWrite`, but found zero."); + goto fail; + } + if (bson_has_field(cmd, "nsInfo.1")) { + CLIENT_ERR( + "expected one namespace in `bulkWrite`, but found more than one. Only one namespace is supported."); + goto fail; + } + if (!mc_iter_document_as_bson(&nsInfo_iter, &nsInfo, status)) { + goto fail; + } + // Ensure `nsInfo` does not already have an `encryptionInformation` field. + if (bson_has_field(&nsInfo, "encryptionInformation")) { + CLIENT_ERR("unexpected `encryptionInformation` present in input `nsInfo`."); + goto fail; + } + } + + // Copy input and append `encryptionInformation` to `nsInfo`. + { + // Append everything from input except `nsInfo`. + bson_copy_to_excluding_noinit(cmd, &out, "nsInfo", NULL); + // Append `nsInfo` array. + bson_t nsInfo_array; + if (!BSON_APPEND_ARRAY_BEGIN(&out, "nsInfo", &nsInfo_array)) { + CLIENT_ERR("unable to begin appending 'nsInfo' array"); + goto fail; + } + bson_t nsInfo_array_0; + if (!BSON_APPEND_DOCUMENT_BEGIN(&nsInfo_array, "0", &nsInfo_array_0)) { + CLIENT_ERR("unable to append 'nsInfo.0' document"); + goto fail; + } + // Copy everything from input `nsInfo`. + bson_concat(&nsInfo_array_0, &nsInfo); + // And append `encryptionInformation`. + if (!_fle2_append_encryptionInformation(ctx, + &nsInfo_array_0, + target_ns, + encryptedFieldConfig, + deleteTokens, + target_coll, + status)) { + goto fail; + } + if (!bson_append_document_end(&nsInfo_array, &nsInfo_array_0)) { + CLIENT_ERR("unable to end appending 'nsInfo' document in array"); + } + if (!bson_append_array_end(&out, &nsInfo_array)) { + CLIENT_ERR("unable to end appending 'nsInfo' array"); + goto fail; + } + // Overwrite `cmd`. + bson_destroy(cmd); + if (!bson_steal(cmd, &out)) { + CLIENT_ERR("failed to steal BSON with encryptionInformation"); + goto fail; + } + } + + goto success; + } if (0 != strcmp(cmd_name, "explain") || cmd_target == MC_TO_MONGOCRYPTD) { - // All commands except "explain" expect "encryptionInformation" + // All commands except "explain" and "bulkWrite" expect "encryptionInformation" // at top-level. "explain" sent to mongocryptd expects // "encryptionInformation" at top-level. - if (!_fle2_append_encryptionInformation(ctx, cmd, ns, encryptedFieldConfig, deleteTokens, coll_name, status)) { + if (!_fle2_append_encryptionInformation(ctx, + cmd, + target_ns, + encryptedFieldConfig, + deleteTokens, + target_coll, + status)) { goto fail; } bson_destroy(&out); @@ -253,7 +335,13 @@ static bool _fle2_insert_encryptionInformation(const mongocrypt_ctx_t *ctx, bson_copy_to(&tmp, &explain); } - if (!_fle2_append_encryptionInformation(ctx, &explain, ns, encryptedFieldConfig, deleteTokens, coll_name, status)) { + if (!_fle2_append_encryptionInformation(ctx, + &explain, + target_ns, + encryptedFieldConfig, + deleteTokens, + target_coll, + status)) { goto fail; } @@ -265,7 +353,7 @@ static bool _fle2_insert_encryptionInformation(const mongocrypt_ctx_t *ctx, bson_copy_to_excluding_noinit(cmd, &out, "explain", NULL); bson_destroy(cmd); if (!bson_steal(cmd, &out)) { - CLIENT_ERR("failed to steal BSON without encryptionInformation"); + CLIENT_ERR("failed to steal BSON with encryptionInformation"); goto fail; } @@ -288,7 +376,7 @@ static bool _mongo_op_collinfo(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) BSON_ASSERT_PARAM(out); ectx = (_mongocrypt_ctx_encrypt_t *)ctx; - cmd = BCON_NEW("name", BCON_UTF8(ectx->coll_name)); + cmd = BCON_NEW("name", BCON_UTF8(ectx->target_coll)); CRYPT_TRACEF(&ectx->parent.crypt->log, "constructed: %s\n", tmp_json(cmd)); _mongocrypt_buffer_steal_from_bson(&ectx->list_collections_filter, cmd); out->data = ectx->list_collections_filter.data; @@ -328,10 +416,46 @@ static bool _set_schema_from_collinfo(mongocrypt_ctx_t *ctx, bson_t *collinfo) { if (!_mongocrypt_buffer_to_bson(&ectx->encrypted_field_config, &efc_bson)) { return _mongocrypt_ctx_fail_w_msg(ctx, "unable to create BSON from encrypted_field_config"); } - if (!mc_EncryptedFieldConfig_parse(&ectx->efc, &efc_bson, ctx->status)) { + if (!mc_EncryptedFieldConfig_parse(&ectx->efc, &efc_bson, ctx->status, ctx->crypt->opts.use_range_v2)) { _mongocrypt_ctx_fail(ctx); return false; } + } else if (0 == strcmp(ectx->cmd_name, "bulkWrite")) { + ectx->used_empty_encryptedFields = true; + // `bulkWrite` is a special case. Sending `bulkWrite` with `jsonSchema` to query analysis results in an error: + // `The bulkWrite command only supports Queryable Encryption` + // + // Add an empty encryptedFields (rather than an empty JSON schema) to ensure `bulkWrite` can be sent to query + // analysis. + bson_t empty_encryptedFields = BSON_INITIALIZER; + { + char *escCollection = bson_strdup_printf("enxcol_.%s.esc", ectx->target_coll); + char *ecocCollection = bson_strdup_printf("enxcol_.%s.ecoc", ectx->target_coll); + bson_t empty_array = BSON_INITIALIZER; + if (!BSON_APPEND_UTF8(&empty_encryptedFields, "escCollection", escCollection)) { + return _mongocrypt_ctx_fail_w_msg(ctx, "failed to append `escCollection`"); + } + if (!BSON_APPEND_UTF8(&empty_encryptedFields, "ecocCollection", ecocCollection)) { + return _mongocrypt_ctx_fail_w_msg(ctx, "failed to append `ecocCollection`"); + } + if (!BSON_APPEND_ARRAY(&empty_encryptedFields, "fields", &empty_array)) { + return _mongocrypt_ctx_fail_w_msg(ctx, "failed to append `fields`"); + } + + bson_destroy(&empty_array); + bson_free(escCollection); + bson_free(ecocCollection); + } + + if (!mc_EncryptedFieldConfig_parse(&ectx->efc, + &empty_encryptedFields, + ctx->status, + ctx->crypt->opts.use_range_v2)) { + bson_destroy(&empty_encryptedFields); + _mongocrypt_ctx_fail(ctx); + return false; + } + _mongocrypt_buffer_steal_from_bson(&ectx->encrypted_field_config, &empty_encryptedFields); } BSON_ASSERT(bson_iter_init(&iter, collinfo)); @@ -458,7 +582,7 @@ static bool _fle2_collect_keys_for_deleteTokens(mongocrypt_ctx_t *ctx) { mc_EncryptedField_t *field; for (field = ectx->efc.fields; field != NULL; field = field->next) { - if (field->has_queries) { + if (field->supported_queries) { if (!_mongocrypt_key_broker_request_id(&ctx->kb, &field->keyId)) { _mongocrypt_key_broker_status(&ctx->kb, ctx->status); _mongocrypt_ctx_fail(ctx); @@ -469,9 +593,10 @@ static bool _fle2_collect_keys_for_deleteTokens(mongocrypt_ctx_t *ctx) { return true; } -/* _fle2_collect_keys_for_compact requests keys required to produce - * compactionTokens. compactionTokens is only applicable to FLE 2. */ -static bool _fle2_collect_keys_for_compact(mongocrypt_ctx_t *ctx) { +/* _fle2_collect_keys_for_compaction requests keys required to produce + * compactionTokens or cleanupTokens. + * compactionTokens and cleanupTokens are only applicable to FLE 2. */ +static bool _fle2_collect_keys_for_compaction(mongocrypt_ctx_t *ctx) { _mongocrypt_ctx_encrypt_t *ectx = (_mongocrypt_ctx_encrypt_t *)ctx; BSON_ASSERT_PARAM(ctx); @@ -483,11 +608,12 @@ static bool _fle2_collect_keys_for_compact(mongocrypt_ctx_t *ctx) { const char *cmd_name = ectx->cmd_name; - if (0 != strcmp(cmd_name, "compactStructuredEncryptionData")) { + if (0 != strcmp(cmd_name, "compactStructuredEncryptionData") + && 0 != strcmp(cmd_name, "cleanupStructuredEncryptionData")) { return true; } - /* compactStructuredEncryptionData must not be sent to mongocryptd. */ + /* (compact/cleanup)StructuredEncryptionData must not be sent to mongocryptd. */ ectx->bypass_query_analysis = true; mc_EncryptedField_t *field; @@ -516,7 +642,7 @@ static bool _mongo_feed_collinfo(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in) } /* Cache the received collinfo. */ - if (!_mongocrypt_cache_add_copy(&ctx->crypt->cache_collinfo, ectx->ns, &as_bson, ctx->status)) { + if (!_mongocrypt_cache_add_copy(&ctx->crypt->cache_collinfo, ectx->target_ns, &as_bson, ctx->status)) { return _mongocrypt_ctx_fail(ctx); } @@ -538,8 +664,12 @@ static bool _mongo_done_collinfo(mongocrypt_ctx_t *ctx) { if (_mongocrypt_buffer_empty(&ectx->schema)) { bson_t empty_collinfo = BSON_INITIALIZER; - /* If no collinfo was fed, cache an empty collinfo. */ - if (!_mongocrypt_cache_add_copy(&ctx->crypt->cache_collinfo, ectx->ns, &empty_collinfo, ctx->status)) { + /* If no collinfo was fed, apply and cache an empty collinfo. */ + if (!_set_schema_from_collinfo(ctx, &empty_collinfo)) { + bson_destroy(&empty_collinfo); + return false; + } + if (!_mongocrypt_cache_add_copy(&ctx->crypt->cache_collinfo, ectx->target_ns, &empty_collinfo, ctx->status)) { bson_destroy(&empty_collinfo); return _mongocrypt_ctx_fail(ctx); } @@ -550,7 +680,7 @@ static bool _mongo_done_collinfo(mongocrypt_ctx_t *ctx) { return false; } - if (!_fle2_collect_keys_for_compact(ctx)) { + if (!_fle2_collect_keys_for_compaction(ctx)) { return false; } @@ -564,6 +694,19 @@ static bool _mongo_done_collinfo(mongocrypt_ctx_t *ctx) { return _try_run_csfle_marking(ctx); } +static const char *_mongo_db_collinfo(mongocrypt_ctx_t *ctx) { + _mongocrypt_ctx_encrypt_t *ectx; + + BSON_ASSERT_PARAM(ctx); + + ectx = (_mongocrypt_ctx_encrypt_t *)ctx; + if (!ectx->target_db) { + _mongocrypt_ctx_fail_w_msg(ctx, "Expected target database for `listCollections`, but none exists."); + return NULL; + } + return ectx->target_db; +} + static bool _fle2_mongo_op_markings(mongocrypt_ctx_t *ctx, bson_t *out) { _mongocrypt_ctx_encrypt_t *ectx; bson_t cmd_bson = BSON_INITIALIZER, encrypted_field_config_bson = BSON_INITIALIZER; @@ -594,10 +737,10 @@ static bool _fle2_mongo_op_markings(mongocrypt_ctx_t *ctx, bson_t *out) { if (!_fle2_insert_encryptionInformation(ctx, cmd_name, out, - ectx->ns, + ectx->target_ns, &encrypted_field_config_bson, NULL /* deleteTokens */, - ectx->coll_name, + ectx->target_coll, ctx->crypt->csfle.okay ? MC_TO_CSFLE : MC_TO_MONGOCRYPTD, ctx->status)) { return _mongocrypt_ctx_fail(ctx); @@ -734,7 +877,7 @@ static bool _collect_key_from_marking(void *ctx, _mongocrypt_buffer_t *in, mongo static bool _mongo_feed_markings(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in) { /* Find keys. */ bson_t as_bson; - bson_iter_t iter; + bson_iter_t iter = {0}; _mongocrypt_ctx_encrypt_t *ectx; BSON_ASSERT_PARAM(ctx); @@ -823,7 +966,7 @@ static bool _mongo_done_markings(mongocrypt_ctx_t *ctx) { /** * @brief Append $db to a command being passed to csfle. */ -static bool _add_dollar_db(const char *cmd_name, bson_t *cmd, const char *db_name, mongocrypt_status_t *status) { +static bool _add_dollar_db(const char *cmd_name, bson_t *cmd, const char *cmd_db, mongocrypt_status_t *status) { bson_t out = BSON_INITIALIZER; bson_t explain = BSON_INITIALIZER; bson_iter_t iter; @@ -831,10 +974,10 @@ static bool _add_dollar_db(const char *cmd_name, bson_t *cmd, const char *db_nam BSON_ASSERT_PARAM(cmd_name); BSON_ASSERT_PARAM(cmd); - BSON_ASSERT_PARAM(db_name); + BSON_ASSERT_PARAM(cmd_db); if (!bson_iter_init_find(&iter, cmd, "$db")) { - if (!BSON_APPEND_UTF8(cmd, "$db", db_name)) { + if (!BSON_APPEND_UTF8(cmd, "$db", cmd_db)) { CLIENT_ERR("failed to append '$db'"); goto fail; } @@ -868,7 +1011,7 @@ static bool _add_dollar_db(const char *cmd_name, bson_t *cmd, const char *db_nam bson_copy_to(&tmp, &explain); } - if (!BSON_APPEND_UTF8(&explain, "$db", db_name)) { + if (!BSON_APPEND_UTF8(&explain, "$db", cmd_db)) { CLIENT_ERR("failed to append '$db'"); goto fail; } @@ -947,7 +1090,7 @@ static bool _try_run_csfle_marking(mongocrypt_ctx_t *ctx) { const char *cmd_name = ectx->cmd_name; - if (!_add_dollar_db(cmd_name, &cmd, ectx->db_name, ctx->status)) { + if (!_add_dollar_db(cmd_name, &cmd, ectx->cmd_db, ctx->status)) { _mongocrypt_ctx_fail(ctx); goto fail_create_cmd; } @@ -975,8 +1118,12 @@ static bool _try_run_csfle_marking(mongocrypt_ctx_t *ctx) { CHECK_CSFLE_ERROR("query_analyzer_create", fail_qa_create); uint32_t marked_bson_len = 0; - uint8_t *marked_bson = - csfle.analyze_query(qa, bson_get_data(&cmd), ectx->ns, (uint32_t)strlen(ectx->ns), &marked_bson_len, status); + uint8_t *marked_bson = csfle.analyze_query(qa, + bson_get_data(&cmd), + ectx->target_ns, + (uint32_t)strlen(ectx->target_ns), + &marked_bson_len, + status); CHECK_CSFLE_ERROR("analyze_query", fail_analyze_query); // Copy out the marked document. @@ -1107,7 +1254,7 @@ static bson_t *generate_delete_tokens(_mongocrypt_crypto_t *crypto, mc_ECOCToken_t *ecoc = NULL; bool loop_ok = false; /* deleteTokens are only necessary for indexed fields. */ - if (!ef->has_queries) { + if (!ef->supported_queries) { goto loop_continue; } @@ -1223,8 +1370,11 @@ typedef struct { // must_omit_encryptionInformation returns true if the command // must omit the "encryptionInformation" field when sent to mongod / mongos. -static moe_result -must_omit_encryptionInformation(const char *command_name, const bson_t *command, mongocrypt_status_t *status) { +static moe_result must_omit_encryptionInformation(const char *command_name, + const bson_t *command, + bool use_range_v2, + const mc_EncryptedFieldConfig_t *efc, + mongocrypt_status_t *status) { // eligible_commands may omit encryptionInformation if the command does not // contain payloads requiring encryption. const char *eligible_commands[] = {"find", "aggregate", "distinct", "count", "insert"}; @@ -1232,10 +1382,28 @@ must_omit_encryptionInformation(const char *command_name, const bson_t *command, bool found = false; // prohibited_commands prohibit encryptionInformation on mongod / mongos. - const char *prohibited_commands[] = {"compactStructuredEncryptionData", "create", "collMod", "createIndexes"}; + const char *prohibited_commands[] = {"cleanupStructuredEncryptionData", "create", "collMod", "createIndexes"}; BSON_ASSERT_PARAM(command_name); BSON_ASSERT_PARAM(command); + BSON_ASSERT_PARAM(efc); + + if (0 == strcmp("compactStructuredEncryptionData", command_name)) { + // `compactStructuredEncryptionData` is a special case: + // - Server 7.0 prohibits `encryptionInformation`. + // - Server 8.0 requires `encryptionInformation` if "range" fields are referenced. Otherwise ignores. + // Only send `encryptionInformation` if "range" fields are present to support both server versions. + bool uses_range_fields = false; + if (use_range_v2) { + for (const mc_EncryptedField_t *ef = efc->fields; ef != NULL; ef = ef->next) { + if (ef->supported_queries & SUPPORTS_RANGE_QUERIES) { + uses_range_fields = true; + break; + } + } + } + return (moe_result){.ok = true, .must_omit = !uses_range_fields}; + } for (i = 0; i < sizeof(prohibited_commands) / sizeof(prohibited_commands[0]); i++) { if (0 == strcmp(prohibited_commands[i], command_name)) { @@ -1254,7 +1422,7 @@ must_omit_encryptionInformation(const char *command_name, const bson_t *command, } bool has_payload_requiring_encryptionInformation = false; - bson_iter_t iter; + bson_iter_t iter = {0}; if (!bson_iter_init(&iter, command)) { CLIENT_ERR("unable to iterate command"); return (moe_result){.ok = false}; @@ -1274,35 +1442,46 @@ must_omit_encryptionInformation(const char *command_name, const bson_t *command, } /* _fle2_append_compactionTokens appends compactionTokens if command_name is - * "compactStructuredEncryptionData" */ -static bool _fle2_append_compactionTokens(_mongocrypt_crypto_t *crypto, + * "compactStructuredEncryptionData" or cleanupTokens if command_name is + * "cleanupStructuredEncryptionData" + */ +static bool _fle2_append_compactionTokens(mongocrypt_t *crypt, _mongocrypt_key_broker_t *kb, mc_EncryptedFieldConfig_t *efc, const char *command_name, bson_t *out, mongocrypt_status_t *status) { - bson_t result_compactionTokens; + bson_t result_compactionTokens = BSON_INITIALIZER; bool ret = false; - BSON_ASSERT_PARAM(crypto); + BSON_ASSERT_PARAM(crypt); BSON_ASSERT_PARAM(kb); BSON_ASSERT_PARAM(efc); BSON_ASSERT_PARAM(command_name); BSON_ASSERT_PARAM(out); + _mongocrypt_crypto_t *crypto = crypt->crypto; - if (0 != strcmp(command_name, "compactStructuredEncryptionData")) { + bool cleanup = (0 == strcmp(command_name, "cleanupStructuredEncryptionData")); + + if (0 != strcmp(command_name, "compactStructuredEncryptionData") && !cleanup) { return true; } - BSON_APPEND_DOCUMENT_BEGIN(out, "compactionTokens", &result_compactionTokens); + if (cleanup) { + BSON_APPEND_DOCUMENT_BEGIN(out, "cleanupTokens", &result_compactionTokens); + } else { + BSON_APPEND_DOCUMENT_BEGIN(out, "compactionTokens", &result_compactionTokens); + } mc_EncryptedField_t *ptr; for (ptr = efc->fields; ptr != NULL; ptr = ptr->next) { - /* Append ECOC token. */ + /* Append tokens. */ _mongocrypt_buffer_t key = {0}; _mongocrypt_buffer_t tokenkey = {0}; mc_CollectionsLevel1Token_t *cl1t = NULL; mc_ECOCToken_t *ecoct = NULL; + mc_ESCToken_t *esct = NULL; + mc_AnchorPaddingTokenRoot_t *padt = NULL; bool ecoc_ok = false; if (!_mongocrypt_key_broker_decrypted_key_by_id(kb, &ptr->keyId, &key)) { @@ -1333,10 +1512,35 @@ static bool _fle2_append_compactionTokens(_mongocrypt_crypto_t *crypto, const _mongocrypt_buffer_t *ecoct_buf = mc_ECOCToken_get(ecoct); - BSON_APPEND_BINARY(&result_compactionTokens, ptr->path, BSON_SUBTYPE_BINARY, ecoct_buf->data, ecoct_buf->len); + if (crypt->opts.use_range_v2 && (ptr->supported_queries & SUPPORTS_RANGE_QUERIES)) { + // Append the document {ecoc: , anchorPaddingToken: } + esct = mc_ESCToken_new(crypto, cl1t, status); + if (!esct) { + goto ecoc_fail; + } + padt = mc_AnchorPaddingTokenRoot_new(crypto, esct, status); + if (!padt) { + goto ecoc_fail; + } + const _mongocrypt_buffer_t *padt_buf = mc_AnchorPaddingTokenRoot_get(padt); + bson_t tokenDoc; + BSON_APPEND_DOCUMENT_BEGIN(&result_compactionTokens, ptr->path, &tokenDoc); + BSON_APPEND_BINARY(&tokenDoc, "ecoc", BSON_SUBTYPE_BINARY, ecoct_buf->data, ecoct_buf->len); + BSON_APPEND_BINARY(&tokenDoc, "anchorPaddingToken", BSON_SUBTYPE_BINARY, padt_buf->data, padt_buf->len); + bson_append_document_end(&result_compactionTokens, &tokenDoc); + } else { + // Append just + BSON_APPEND_BINARY(&result_compactionTokens, + ptr->path, + BSON_SUBTYPE_BINARY, + ecoct_buf->data, + ecoct_buf->len); + } ecoc_ok = true; ecoc_fail: + mc_AnchorPaddingTokenRoot_destroy(padt); + mc_ESCToken_destroy(esct); mc_ECOCToken_destroy(ecoct); mc_CollectionsLevel1Token_destroy(cl1t); _mongocrypt_buffer_cleanup(&key); @@ -1363,11 +1567,63 @@ _fle2_strip_encryptionInformation(const char *cmd_name, bson_t *cmd /* in and ou BSON_ASSERT_PARAM(cmd_name); BSON_ASSERT_PARAM(cmd); - if (0 != strcmp(cmd_name, "explain")) { + if (0 != strcmp(cmd_name, "explain") && 0 != strcmp(cmd_name, "bulkWrite")) { bson_copy_to_excluding_noinit(cmd, &stripped, "encryptionInformation", NULL); goto success; } + if (0 == strcmp(cmd_name, "bulkWrite")) { + // Get the single `nsInfo` document from the input command. + bson_t nsInfo; // Non-owning. + { + bson_iter_t nsInfo_iter; + if (!bson_iter_init(&nsInfo_iter, cmd)) { + CLIENT_ERR("failed to iterate command"); + goto fail; + } + if (!bson_iter_find_descendant(&nsInfo_iter, "nsInfo.0", &nsInfo_iter)) { + CLIENT_ERR("expected one namespace in `bulkWrite`, but found zero."); + goto fail; + } + if (bson_has_field(cmd, "nsInfo.1")) { + CLIENT_ERR( + "expected one namespace in `bulkWrite`, but found more than one. Only one namespace is supported."); + goto fail; + } + if (!mc_iter_document_as_bson(&nsInfo_iter, &nsInfo, status)) { + goto fail; + } + } + + // Copy input and exclude `encryptionInformation` from `nsInfo`. + { + // Append everything from input except `nsInfo`. + bson_copy_to_excluding_noinit(cmd, &stripped, "nsInfo", NULL); + // Append `nsInfo` array. + bson_t nsInfo_array; + if (!BSON_APPEND_ARRAY_BEGIN(&stripped, "nsInfo", &nsInfo_array)) { + CLIENT_ERR("unable to begin appending 'nsInfo' array"); + goto fail; + } + bson_t nsInfo_array_0; + if (!BSON_APPEND_DOCUMENT_BEGIN(&nsInfo_array, "0", &nsInfo_array_0)) { + CLIENT_ERR("unable to append 'nsInfo.0' document"); + goto fail; + } + // Copy everything from input `nsInfo` and exclude `encryptionInformation`. + bson_copy_to_excluding_noinit(&nsInfo, &nsInfo_array_0, "encryptionInformation", NULL); + if (!bson_append_document_end(&nsInfo_array, &nsInfo_array_0)) { + CLIENT_ERR("unable to end appending 'nsInfo' document in array"); + } + if (!bson_append_array_end(&stripped, &nsInfo_array)) { + CLIENT_ERR("unable to end appending 'nsInfo' array"); + goto fail; + } + } + + goto success; + } + // The 'explain' command is a special case. // 'encryptionInformation' is returned from mongocryptd and csfle nested // inside 'explain'. Example: @@ -1451,7 +1707,7 @@ static bool _fle2_finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { bson_copy_to(&original_cmd_bson, &converted); } else { bson_t as_bson; - bson_iter_t iter; + bson_iter_t iter = {0}; if (!_mongocrypt_buffer_to_bson(&ectx->marked_cmd, &as_bson)) { return _mongocrypt_ctx_fail_w_msg(ctx, "malformed bson"); @@ -1488,7 +1744,11 @@ static bool _fle2_finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { } } - moe_result result = must_omit_encryptionInformation(command_name, &converted, ctx->status); + moe_result result = must_omit_encryptionInformation(command_name, + &converted, + ctx->crypt->opts.use_range_v2, + &ectx->efc, + ctx->status); if (!result.ok) { bson_destroy(&converted); bson_destroy(deleteTokens); @@ -1496,14 +1756,14 @@ static bool _fle2_finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { } /* Append a new 'encryptionInformation'. */ - if (!result.must_omit) { + if (!result.must_omit && !ectx->used_empty_encryptedFields) { if (!_fle2_insert_encryptionInformation(ctx, command_name, &converted, - ectx->ns, + ectx->target_ns, &encrypted_field_config_bson, deleteTokens, - ectx->coll_name, + ectx->target_coll, MC_TO_MONGOD, ctx->status)) { bson_destroy(&converted); @@ -1513,12 +1773,7 @@ static bool _fle2_finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { } bson_destroy(deleteTokens); - if (!_fle2_append_compactionTokens(ctx->crypt->crypto, - &ctx->kb, - &ectx->efc, - command_name, - &converted, - ctx->status)) { + if (!_fle2_append_compactionTokens(ctx->crypt, &ctx->kb, &ectx->efc, command_name, &converted, ctx->status)) { bson_destroy(&converted); return _mongocrypt_ctx_fail(ctx); } @@ -1527,7 +1782,7 @@ static bool _fle2_finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { bson_iter_t iter; if (bson_iter_init_find(&iter, &original_cmd_bson, "$db")) { if (!bson_iter_init_find(&iter, &converted, "$db")) { - BSON_APPEND_UTF8(&converted, "$db", ectx->db_name); + BSON_APPEND_UTF8(&converted, "$db", ectx->cmd_db); } } @@ -1545,6 +1800,9 @@ static bool FLE2RangeFindDriverSpec_to_ciphertexts(mongocrypt_ctx_t *ctx, mongoc BSON_ASSERT_PARAM(ctx); BSON_ASSERT_PARAM(out); + bson_t with_placholders = BSON_INITIALIZER; + bson_t with_ciphertexts = BSON_INITIALIZER; + if (!ctx->opts.rangeopts.set) { _mongocrypt_ctx_fail_w_msg(ctx, "Expected RangeOpts to be set for Range Find"); goto fail; @@ -1554,8 +1812,6 @@ static bool FLE2RangeFindDriverSpec_to_ciphertexts(mongocrypt_ctx_t *ctx, mongoc goto fail; } - bson_t with_placholders = BSON_INITIALIZER; - bson_t with_ciphertexts = BSON_INITIALIZER; bson_t in_bson; if (!_mongocrypt_buffer_to_bson(&ectx->original_cmd, &in_bson)) { _mongocrypt_ctx_fail_w_msg(ctx, "unable to convert input to BSON"); @@ -1663,7 +1919,13 @@ static bool _fle2_finalize_explicit(mongocrypt_ctx_t *ctx, mongocrypt_binary_t * marking.type = MONGOCRYPT_MARKING_FLE2_ENCRYPTION; if (ctx->opts.query_type.set) { switch (ctx->opts.query_type.value) { - case MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW: + case MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED: + if (ctx->crypt->opts.use_range_v2) { + _mongocrypt_ctx_fail_w_msg(ctx, "Cannot use rangePreview query type with Range V2"); + goto fail; + } + // fallthrough + case MONGOCRYPT_QUERY_TYPE_RANGE: case MONGOCRYPT_QUERY_TYPE_EQUALITY: marking.fle2.type = MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND; break; default: _mongocrypt_ctx_fail_w_msg(ctx, "Invalid value for EncryptOpts.queryType"); goto fail; } @@ -1674,7 +1936,13 @@ static bool _fle2_finalize_explicit(mongocrypt_ctx_t *ctx, mongocrypt_binary_t * switch (ctx->opts.index_type.value) { case MONGOCRYPT_INDEX_TYPE_EQUALITY: marking.fle2.algorithm = MONGOCRYPT_FLE2_ALGORITHM_EQUALITY; break; case MONGOCRYPT_INDEX_TYPE_NONE: marking.fle2.algorithm = MONGOCRYPT_FLE2_ALGORITHM_UNINDEXED; break; - case MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW: marking.fle2.algorithm = MONGOCRYPT_FLE2_ALGORITHM_RANGE; break; + case MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW_DEPRECATED: + if (ctx->crypt->opts.use_range_v2) { + _mongocrypt_ctx_fail_w_msg(ctx, "Cannot use rangePreview index type with Range V2"); + goto fail; + } + // fallthrough + case MONGOCRYPT_INDEX_TYPE_RANGE: marking.fle2.algorithm = MONGOCRYPT_FLE2_ALGORITHM_RANGE; break; default: // This might be unreachable because of other validation. Better safe than // sorry. @@ -1695,7 +1963,11 @@ static bool _fle2_finalize_explicit(mongocrypt_ctx_t *ctx, mongocrypt_binary_t * // RangeOpts with query_type is handled above. BSON_ASSERT(!ctx->opts.query_type.set); - if (!mc_RangeOpts_to_FLE2RangeInsertSpec(&ctx->opts.rangeopts.value, &old_v, &new_v, ctx->status)) { + if (!mc_RangeOpts_to_FLE2RangeInsertSpec(&ctx->opts.rangeopts.value, + &old_v, + &new_v, + ctx->crypt->opts.use_range_v2, + ctx->status)) { _mongocrypt_ctx_fail(ctx); goto fail; } @@ -1730,7 +2002,7 @@ static bool _fle2_finalize_explicit(mongocrypt_ctx_t *ctx, mongocrypt_binary_t * } if (ctx->opts.contention_factor.set) { - marking.fle2.maxContentionCounter = ctx->opts.contention_factor.value; + marking.fle2.maxContentionFactor = ctx->opts.contention_factor.value; } else if (ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_EQUALITY) { _mongocrypt_ctx_fail_w_msg(ctx, "contention factor required for indexed algorithm"); goto fail; @@ -1764,7 +2036,7 @@ static bool _fle2_finalize_explicit(mongocrypt_ctx_t *ctx, mongocrypt_binary_t * static bool _finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { bson_t as_bson, converted; - bson_iter_t iter; + bson_iter_t iter = {0}; _mongocrypt_ctx_encrypt_t *ectx; bool res; @@ -1811,7 +2083,7 @@ static bool _finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { bson_iter_t iter; if (bson_iter_init_find(&iter, &original_cmd_bson, "$db")) { if (!bson_iter_init_find(&iter, &converted, "$db")) { - BSON_APPEND_UTF8(&converted, "$db", ectx->db_name); + BSON_APPEND_UTF8(&converted, "$db", ectx->cmd_db); } } } else { @@ -1869,9 +2141,10 @@ static void _cleanup(mongocrypt_ctx_t *ctx) { } ectx = (_mongocrypt_ctx_encrypt_t *)ctx; - bson_free(ectx->ns); - bson_free(ectx->db_name); - bson_free(ectx->coll_name); + bson_free(ectx->target_ns); + bson_free(ectx->cmd_db); + bson_free(ectx->target_db); + bson_free(ectx->target_coll); _mongocrypt_buffer_cleanup(&ectx->list_collections_filter); _mongocrypt_buffer_cleanup(&ectx->schema); _mongocrypt_buffer_cleanup(&ectx->encrypted_field_config); @@ -1903,7 +2176,7 @@ static bool _try_schema_from_schema_map(mongocrypt_ctx_t *ctx) { return _mongocrypt_ctx_fail_w_msg(ctx, "malformed schema map"); } - if (bson_iter_init_find(&iter, &schema_map, ectx->ns)) { + if (bson_iter_init_find(&iter, &schema_map, ectx->target_ns)) { if (!_mongocrypt_buffer_copy_from_document_iter(&ectx->schema, &iter)) { return _mongocrypt_ctx_fail_w_msg(ctx, "malformed schema map"); } @@ -1939,7 +2212,7 @@ static bool _fle2_try_encrypted_field_config_from_map(mongocrypt_ctx_t *ctx) { return _mongocrypt_ctx_fail_w_msg(ctx, "unable to convert encrypted_field_config_map to BSON"); } - if (bson_iter_init_find(&iter, &encrypted_field_config_map, ectx->ns)) { + if (bson_iter_init_find(&iter, &encrypted_field_config_map, ectx->target_ns)) { if (!_mongocrypt_buffer_copy_from_document_iter(&ectx->encrypted_field_config, &iter)) { return _mongocrypt_ctx_fail_w_msg(ctx, "unable to copy encrypted_field_config from " @@ -1949,7 +2222,7 @@ static bool _fle2_try_encrypted_field_config_from_map(mongocrypt_ctx_t *ctx) { if (!_mongocrypt_buffer_to_bson(&ectx->encrypted_field_config, &efc_bson)) { return _mongocrypt_ctx_fail_w_msg(ctx, "unable to create BSON from encrypted_field_config"); } - if (!mc_EncryptedFieldConfig_parse(&ectx->efc, &efc_bson, ctx->status)) { + if (!mc_EncryptedFieldConfig_parse(&ectx->efc, &efc_bson, ctx->status, ctx->crypt->opts.use_range_v2)) { _mongocrypt_ctx_fail(ctx); return false; } @@ -1970,18 +2243,32 @@ static bool _try_schema_from_cache(mongocrypt_ctx_t *ctx) { /* Otherwise, we need a remote schema. Check if we have a response to * listCollections cached. */ - if (!_mongocrypt_cache_get(&ctx->crypt->cache_collinfo, ectx->ns /* null terminated */, (void **)&collinfo)) { + if (!_mongocrypt_cache_get(&ctx->crypt->cache_collinfo, + ectx->target_ns /* null terminated */, + (void **)&collinfo)) { return _mongocrypt_ctx_fail_w_msg(ctx, "failed to retrieve from cache"); } if (collinfo) { if (!_set_schema_from_collinfo(ctx, collinfo)) { + bson_destroy(collinfo); return _mongocrypt_ctx_fail(ctx); } ctx->state = MONGOCRYPT_CTX_NEED_MONGO_MARKINGS; } else { /* we need to get it. */ ctx->state = MONGOCRYPT_CTX_NEED_MONGO_COLLINFO; + if (ectx->target_db) { + if (!ctx->crypt->opts.use_need_mongo_collinfo_with_db_state) { + _mongocrypt_ctx_fail_w_msg( + ctx, + "Fetching remote collection information on separate databases is not supported. Try " + "upgrading driver, or specify a local schemaMap or encryptedFieldsMap."); + return false; + } + // Target database may differ from command database. Request collection info from target database. + ctx->state = MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB; + } } bson_destroy(collinfo); @@ -2222,7 +2509,9 @@ static bool explicit_encrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *ms return _mongocrypt_ctx_fail_w_msg(ctx, "contention factor is required for indexed algorithm"); } - if (ctx->opts.index_type.set && ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW) { + if (ctx->opts.index_type.set + && (ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_RANGE + || ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW_DEPRECATED)) { if (!ctx->opts.contention_factor.set) { return _mongocrypt_ctx_fail_w_msg(ctx, "contention factor is required for range indexed algorithm"); } @@ -2242,8 +2531,14 @@ static bool explicit_encrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *ms bool matches = false; switch (ctx->opts.query_type.value) { - case MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW: - matches = (ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW); + case MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED: + // Don't allow deprecated query type if we are using new index type. + matches = (ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW_DEPRECATED); + break; + case MONGOCRYPT_QUERY_TYPE_RANGE: + // New query type is compatible with both new and old index types. + matches = (ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW_DEPRECATED + || ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_RANGE); break; case MONGOCRYPT_QUERY_TYPE_EQUALITY: matches = (ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_EQUALITY); @@ -2317,7 +2612,9 @@ bool mongocrypt_ctx_explicit_encrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_bina if (!explicit_encrypt_init(ctx, msg)) { return false; } - if (ctx->opts.query_type.set && ctx->opts.query_type.value == MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW) { + if (ctx->opts.query_type.set + && (ctx->opts.query_type.value == MONGOCRYPT_QUERY_TYPE_RANGE + || ctx->opts.query_type.value == MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED)) { return _mongocrypt_ctx_fail_w_msg(ctx, "Encrypt may not be used for range queries. Use EncryptExpression."); } return true; @@ -2327,22 +2624,77 @@ bool mongocrypt_ctx_explicit_encrypt_expression_init(mongocrypt_ctx_t *ctx, mong if (!explicit_encrypt_init(ctx, msg)) { return false; } - if (!ctx->opts.query_type.set || ctx->opts.query_type.value != MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW) { + if (!ctx->opts.query_type.set + || !(ctx->opts.query_type.value == MONGOCRYPT_QUERY_TYPE_RANGE + || ctx->opts.query_type.value == MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED)) { return _mongocrypt_ctx_fail_w_msg(ctx, "EncryptExpression may only be used for range queries."); } return true; } +static bool _check_cmd_for_auto_encrypt_bulkWrite(mongocrypt_binary_t *cmd, + char **target_db, + char **target_coll, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(cmd); + BSON_ASSERT_PARAM(target_db); + BSON_ASSERT_PARAM(target_coll); + + bson_t as_bson; + bson_iter_t cmd_iter = {0}; + + if (!_mongocrypt_binary_to_bson(cmd, &as_bson) || !bson_iter_init(&cmd_iter, &as_bson)) { + CLIENT_ERR("invalid command BSON"); + return false; + } + + bson_iter_t ns_iter = cmd_iter; + if (!bson_iter_find_descendant(&ns_iter, "nsInfo.0.ns", &ns_iter)) { + CLIENT_ERR("failed to find namespace in `bulkWrite` command"); + return false; + } + + if (!BSON_ITER_HOLDS_UTF8(&ns_iter)) { + CLIENT_ERR("expected namespace to be UTF8, got: %s", mc_bson_type_to_string(bson_iter_type(&ns_iter))); + return false; + } + + const char *target_ns = bson_iter_utf8(&ns_iter, NULL /* length */); + // Parse `target_ns` into "." + const char *dot = strstr(target_ns, "."); + if (!dot) { + CLIENT_ERR("expected namespace to contain dot, got: %s", target_ns); + return false; + } + *target_coll = bson_strdup(dot + 1); + // Get the database from the `ns` field (which may differ from `cmd_db`). + ptrdiff_t db_len = dot - target_ns; + if ((uint64_t)db_len > SIZE_MAX) { + CLIENT_ERR("unexpected database length exceeds %zu", SIZE_MAX); + return false; + } + *target_db = bson_strndup(target_ns, (size_t)db_len); + + // Ensure only one `nsInfo` element is present. + // Query analysis (mongocryptd/crypt_shared) currently only supports one namespace. + if (bson_has_field(&as_bson, "nsInfo.1")) { + CLIENT_ERR("expected one namespace in `bulkWrite`, but found more than one. Only one namespace is supported."); + return false; + } + + return true; +} + static bool -_check_cmd_for_auto_encrypt(mongocrypt_binary_t *cmd, bool *bypass, char **collname, mongocrypt_status_t *status) { +_check_cmd_for_auto_encrypt(mongocrypt_binary_t *cmd, bool *bypass, char **target_coll, mongocrypt_status_t *status) { bson_t as_bson; - bson_iter_t iter, ns_iter; + bson_iter_t iter = {0}, target_coll_iter; const char *cmd_name; bool eligible = false; BSON_ASSERT_PARAM(cmd); BSON_ASSERT_PARAM(bypass); - BSON_ASSERT_PARAM(collname); + BSON_ASSERT_PARAM(target_coll); *bypass = false; @@ -2366,22 +2718,22 @@ _check_cmd_for_auto_encrypt(mongocrypt_binary_t *cmd, bool *bypass, char **colln CLIENT_ERR("explain value is not a document"); return false; } - if (!bson_iter_recurse(&iter, &ns_iter)) { + if (!bson_iter_recurse(&iter, &target_coll_iter)) { CLIENT_ERR("malformed BSON for encrypt command"); return false; } - if (!bson_iter_next(&ns_iter)) { + if (!bson_iter_next(&target_coll_iter)) { CLIENT_ERR("invalid empty BSON"); return false; } } else { - memcpy(&ns_iter, &iter, sizeof(iter)); + memcpy(&target_coll_iter, &iter, sizeof(iter)); } - if (BSON_ITER_HOLDS_UTF8(&ns_iter)) { - *collname = bson_strdup(bson_iter_utf8(&ns_iter, NULL)); + if (BSON_ITER_HOLDS_UTF8(&target_coll_iter)) { + *target_coll = bson_strdup(bson_iter_utf8(&target_coll_iter, NULL)); } else { - *collname = NULL; + *target_coll = NULL; } /* check if command is eligible for auto encryption, bypassed, or ineligible. @@ -2461,6 +2813,8 @@ _check_cmd_for_auto_encrypt(mongocrypt_binary_t *cmd, bool *bypass, char **colln *bypass = true; } else if (0 == strcmp(cmd_name, "compactStructuredEncryptionData")) { eligible = true; + } else if (0 == strcmp(cmd_name, "cleanupStructuredEncryptionData")) { + eligible = true; } else if (0 == strcmp(cmd_name, "collMod")) { eligible = true; } else if (0 == strcmp(cmd_name, "hello")) { @@ -2471,15 +2825,23 @@ _check_cmd_for_auto_encrypt(mongocrypt_binary_t *cmd, bool *bypass, char **colln *bypass = true; } else if (0 == strcmp(cmd_name, "getLog")) { *bypass = true; + } else if (0 == strcmp(cmd_name, "createSearchIndexes")) { + *bypass = true; + } else if (0 == strcmp(cmd_name, "listSearchIndexes")) { + *bypass = true; + } else if (0 == strcmp(cmd_name, "dropSearchIndex")) { + *bypass = true; + } else if (0 == strcmp(cmd_name, "updateSearchIndex")) { + *bypass = true; } /* database/client commands are ineligible. */ if (eligible) { - if (!*collname) { + if (!*target_coll) { CLIENT_ERR("non-collection command not supported for auto encryption: %s", cmd_name); return false; } - if (0 == strlen(*collname)) { + if (0 == strlen(*target_coll)) { CLIENT_ERR("empty collection name on command: %s", cmd_name); return false; } @@ -2507,7 +2869,6 @@ static bool needs_ismaster_check(mongocrypt_ctx_t *ctx) { bool mongocrypt_ctx_encrypt_init(mongocrypt_ctx_t *ctx, const char *db, int32_t db_len, mongocrypt_binary_t *cmd) { _mongocrypt_ctx_encrypt_t *ectx; _mongocrypt_ctx_opts_spec_t opts_spec; - bool bypass; if (!ctx) { return false; @@ -2529,15 +2890,13 @@ bool mongocrypt_ctx_encrypt_init(mongocrypt_ctx_t *ctx, const char *db, int32_t ctx->vtable.mongo_op_collinfo = _mongo_op_collinfo; ctx->vtable.mongo_feed_collinfo = _mongo_feed_collinfo; ctx->vtable.mongo_done_collinfo = _mongo_done_collinfo; + ctx->vtable.mongo_db_collinfo = _mongo_db_collinfo; ctx->vtable.mongo_op_collinfo = _mongo_op_collinfo; ctx->vtable.mongo_op_markings = _mongo_op_markings; ctx->vtable.mongo_feed_markings = _mongo_feed_markings; ctx->vtable.mongo_done_markings = _mongo_done_markings; ctx->vtable.finalize = _finalize; ctx->vtable.cleanup = _cleanup; - ctx->vtable.mongo_op_collinfo = _mongo_op_collinfo; - ctx->vtable.mongo_feed_collinfo = _mongo_feed_collinfo; - ctx->vtable.mongo_done_collinfo = _mongo_done_collinfo; ectx->bypass_query_analysis = ctx->crypt->opts.bypass_query_analysis; if (!cmd || !cmd->data) { @@ -2551,27 +2910,38 @@ bool mongocrypt_ctx_encrypt_init(mongocrypt_ctx_t *ctx, const char *db, int32_t return _mongocrypt_ctx_fail(ctx); } - if (!_check_cmd_for_auto_encrypt(cmd, &bypass, &ectx->coll_name, ctx->status)) { - return _mongocrypt_ctx_fail(ctx); + if (!_mongocrypt_validate_and_copy_string(db, db_len, &ectx->cmd_db) || 0 == strlen(ectx->cmd_db)) { + return _mongocrypt_ctx_fail_w_msg(ctx, "invalid db"); } - if (bypass) { - ctx->nothing_to_do = true; - ctx->state = MONGOCRYPT_CTX_READY; - return true; - } + if (0 == strcmp(ectx->cmd_name, "bulkWrite")) { + // Handle `bulkWrite` as a special case. + // `bulkWrite` includes the target namespaces in an `nsInfo` field. + // Only one target namespace is supported. + if (!_check_cmd_for_auto_encrypt_bulkWrite(cmd, &ectx->target_db, &ectx->target_coll, ctx->status)) { + return _mongocrypt_ctx_fail(ctx); + } - /* if _check_cmd_for_auto_encrypt did not bypass or error, a collection name - * must have been set. */ - if (!ectx->coll_name) { - return _mongocrypt_ctx_fail_w_msg(ctx, "unexpected error: did not bypass or error but no collection name"); - } + ectx->target_ns = bson_strdup_printf("%s.%s", ectx->target_db, ectx->target_coll); + } else { + bool bypass; + if (!_check_cmd_for_auto_encrypt(cmd, &bypass, &ectx->target_coll, ctx->status)) { + return _mongocrypt_ctx_fail(ctx); + } - if (!_mongocrypt_validate_and_copy_string(db, db_len, &ectx->db_name) || 0 == strlen(ectx->db_name)) { - return _mongocrypt_ctx_fail_w_msg(ctx, "invalid db"); - } + if (bypass) { + ctx->nothing_to_do = true; + ctx->state = MONGOCRYPT_CTX_READY; + return true; + } - ectx->ns = bson_strdup_printf("%s.%s", ectx->db_name, ectx->coll_name); + /* if _check_cmd_for_auto_encrypt did not bypass or error, a collection name + * must have been set. */ + if (!ectx->target_coll) { + return _mongocrypt_ctx_fail_w_msg(ctx, "unexpected error: did not bypass or error but no collection name"); + } + ectx->target_ns = bson_strdup_printf("%s.%s", ectx->cmd_db, ectx->target_coll); + } if (ctx->opts.kek.provider.aws.region || ctx->opts.kek.provider.aws.cmk) { return _mongocrypt_ctx_fail_w_msg(ctx, "aws masterkey options must not be set"); @@ -2593,7 +2963,7 @@ bool mongocrypt_ctx_encrypt_init(mongocrypt_ctx_t *ctx, const char *db, int32_t "%s (%s=\"%s\", %s=%d, %s=\"%s\")", BSON_FUNC, "db", - ectx->db_name, + ectx->cmd_db, "db_len", db_len, "cmd", @@ -2672,6 +3042,17 @@ static bool mongocrypt_ctx_encrypt_ismaster_done(mongocrypt_ctx_t *ctx) { /* Otherwise, we need the the driver to fetch the schema. */ if (_mongocrypt_buffer_empty(&ectx->schema)) { ctx->state = MONGOCRYPT_CTX_NEED_MONGO_COLLINFO; + if (ectx->target_db) { + if (!ctx->crypt->opts.use_need_mongo_collinfo_with_db_state) { + _mongocrypt_ctx_fail_w_msg( + ctx, + "Fetching remote collection information on separate databases is not supported. Try " + "upgrading driver, or specify a local schemaMap or encryptedFieldsMap."); + return false; + } + // Target database may differ from command database. Request collection info from target database. + ctx->state = MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB; + } } } @@ -2681,7 +3062,7 @@ static bool mongocrypt_ctx_encrypt_ismaster_done(mongocrypt_ctx_t *ctx) { return false; } - if (!_fle2_collect_keys_for_compact(ctx)) { + if (!_fle2_collect_keys_for_compaction(ctx)) { return false; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-private.h index 1500686..dcf0312 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-private.h @@ -39,12 +39,17 @@ typedef enum { typedef enum { MONGOCRYPT_INDEX_TYPE_NONE = 1, MONGOCRYPT_INDEX_TYPE_EQUALITY = 2, - MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW = 3 + MONGOCRYPT_INDEX_TYPE_RANGE = 3, + MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW_DEPRECATED = 4 } mongocrypt_index_type_t; const char *_mongocrypt_index_type_to_string(mongocrypt_index_type_t val); -typedef enum { MONGOCRYPT_QUERY_TYPE_EQUALITY = 1, MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW = 2 } mongocrypt_query_type_t; +typedef enum { + MONGOCRYPT_QUERY_TYPE_EQUALITY = 1, + MONGOCRYPT_QUERY_TYPE_RANGE = 2, + MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED = 3 +} mongocrypt_query_type_t; const char *_mongocrypt_query_type_to_string(mongocrypt_query_type_t val); @@ -84,6 +89,7 @@ typedef struct __mongocrypt_ctx_opts_t { /* All derived contexts may override these methods. */ typedef struct { + const char *(*mongo_db_collinfo)(mongocrypt_ctx_t *ctx); bool (*mongo_op_collinfo)(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out); bool (*mongo_feed_collinfo)(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in); bool (*mongo_done_collinfo)(mongocrypt_ctx_t *ctx); @@ -129,9 +135,22 @@ bool _mongocrypt_ctx_fail_w_msg(mongocrypt_ctx_t *ctx, const char *msg); typedef struct { mongocrypt_ctx_t parent; bool explicit; - char *coll_name; - char *db_name; - char *ns; + + // `cmd_db` is the command database (appended as `$db`). + char *cmd_db; + + // `target_ns` is the target namespace "." for the operation. May be associated with + // jsonSchema (CSFLE) or encryptedFields (QE). For `bulkWrite`, the target namespace database may differ from + // `cmd_db`. + char *target_ns; + + // `target_db` is the target database for the operation. For `bulkWrite`, the target namespace database may differ + // from `cmd_db`. If `target_db` is NULL, the target namespace database is the same as `cmd_db`. + char *target_db; + + // `target_coll` is the target namespace collection name. + char *target_coll; + _mongocrypt_buffer_t list_collections_filter; _mongocrypt_buffer_t schema; /* TODO CDRIVER-3150: audit + rename these buffers. @@ -156,13 +175,19 @@ typedef struct { * schema, and there were siblings. */ bool collinfo_has_siblings; /* encrypted_field_config is set when: - * 1. . is present in an encrypted_field_config_map. + * 1. `target_ns` is present in an encrypted_field_config_map. * 2. (TODO MONGOCRYPT-414) The collection has encryptedFields in the * response to listCollections. encrypted_field_config is true if and only if * encryption is using FLE 2.0. + * 3. The `bulkWrite` command is processed and needs an empty encryptedFields to be processed by query analysis. + * (`bulkWrite` does not support empty JSON schema). */ _mongocrypt_buffer_t encrypted_field_config; mc_EncryptedFieldConfig_t efc; + // `used_empty_encryptedFields` is true if the collection has no JSON schema or encryptedFields, + // yet an empty encryptedFields was constructed to support query analysis. + // When true, an empty encryptedFields is sent to query analysis, but not appended to the final command. + bool used_empty_encryptedFields; /* bypass_query_analysis is set to true to skip the * MONGOCRYPT_CTX_NEED_MONGO_MARKINGS state. */ bool bypass_query_analysis; diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c index e464771..15ba3d7 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c @@ -258,8 +258,15 @@ bool mongocrypt_ctx_setopt_algorithm(mongocrypt_ctx_t *ctx, const char *algorith } else if (mstr_eq_ignore_case(algo_str, mstrv_lit(MONGOCRYPT_ALGORITHM_UNINDEXED_STR))) { ctx->opts.index_type.value = MONGOCRYPT_INDEX_TYPE_NONE; ctx->opts.index_type.set = true; - } else if (mstr_eq_ignore_case(algo_str, mstrv_lit(MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR))) { - ctx->opts.index_type.value = MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW; + } else if (mstr_eq_ignore_case(algo_str, mstrv_lit(MONGOCRYPT_ALGORITHM_RANGE_STR))) { + ctx->opts.index_type.value = MONGOCRYPT_INDEX_TYPE_RANGE; + ctx->opts.index_type.set = true; + } else if (mstr_eq_ignore_case(algo_str, mstrv_lit(MONGOCRYPT_ALGORITHM_RANGEPREVIEW_DEPRECATED_STR))) { + if (ctx->crypt->opts.use_range_v2) { + _mongocrypt_ctx_fail_w_msg(ctx, "Algorithm 'rangePreview' is deprecated, please use 'range'"); + return false; + } + ctx->opts.index_type.value = MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW_DEPRECATED; ctx->opts.index_type.set = true; } else { char *error = bson_strdup_printf("unsupported algorithm string \"%.*s\"", @@ -379,6 +386,7 @@ bool mongocrypt_ctx_mongo_op(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { } switch (ctx->state) { + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: CHECK_AND_CALL(mongo_op_collinfo, ctx, out); case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: CHECK_AND_CALL(mongo_op_markings, ctx, out); case MONGOCRYPT_CTX_NEED_MONGO_KEYS: CHECK_AND_CALL(mongo_op_keys, ctx, out); @@ -391,6 +399,38 @@ bool mongocrypt_ctx_mongo_op(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { } } +const char *mongocrypt_ctx_mongo_db(mongocrypt_ctx_t *ctx) { + if (!ctx) { + return NULL; + } + if (!ctx->initialized) { + _mongocrypt_ctx_fail_w_msg(ctx, "ctx NULL or uninitialized"); + return NULL; + } + + switch (ctx->state) { + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: { + if (!ctx->vtable.mongo_db_collinfo) { + _mongocrypt_ctx_fail_w_msg(ctx, "not applicable to context"); + return NULL; + } + return ctx->vtable.mongo_db_collinfo(ctx); + } + case MONGOCRYPT_CTX_ERROR: return false; + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: + case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: + case MONGOCRYPT_CTX_NEED_MONGO_KEYS: + case MONGOCRYPT_CTX_DONE: + case MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: + case MONGOCRYPT_CTX_NEED_KMS: + case MONGOCRYPT_CTX_READY: + default: { + _mongocrypt_ctx_fail_w_msg(ctx, "wrong state"); + return NULL; + } + } +} + bool mongocrypt_ctx_mongo_feed(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in) { if (!ctx) { return false; @@ -412,6 +452,7 @@ bool mongocrypt_ctx_mongo_feed(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *in) { } switch (ctx->state) { + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: CHECK_AND_CALL(mongo_feed_collinfo, ctx, in); case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: CHECK_AND_CALL(mongo_feed_markings, ctx, in); case MONGOCRYPT_CTX_NEED_MONGO_KEYS: CHECK_AND_CALL(mongo_feed_keys, ctx, in); @@ -433,6 +474,7 @@ bool mongocrypt_ctx_mongo_done(mongocrypt_ctx_t *ctx) { } switch (ctx->state) { + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: CHECK_AND_CALL(mongo_done_collinfo, ctx); case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: CHECK_AND_CALL(mongo_done_markings, ctx); case MONGOCRYPT_CTX_NEED_MONGO_KEYS: CHECK_AND_CALL(mongo_done_keys, ctx); @@ -476,6 +518,7 @@ mongocrypt_kms_ctx_t *mongocrypt_ctx_next_kms_ctx(mongocrypt_ctx_t *ctx) { case MONGOCRYPT_CTX_ERROR: return NULL; case MONGOCRYPT_CTX_DONE: case MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: case MONGOCRYPT_CTX_NEED_MONGO_KEYS: case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: @@ -504,6 +547,8 @@ bool mongocrypt_ctx_provide_kms_providers(mongocrypt_ctx_t *ctx, mongocrypt_bina return false; } + _mongocrypt_opts_kms_providers_init(&ctx->per_ctx_kms_providers); + if (!_mongocrypt_parse_kms_providers(kms_providers_definition, &ctx->per_ctx_kms_providers, ctx->status, @@ -545,6 +590,7 @@ bool mongocrypt_ctx_kms_done(mongocrypt_ctx_t *ctx) { case MONGOCRYPT_CTX_ERROR: return false; case MONGOCRYPT_CTX_DONE: case MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: case MONGOCRYPT_CTX_NEED_MONGO_KEYS: case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: @@ -575,6 +621,7 @@ bool mongocrypt_ctx_finalize(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *out) { case MONGOCRYPT_CTX_DONE: case MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS: case MONGOCRYPT_CTX_NEED_KMS: + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: case MONGOCRYPT_CTX_NEED_MONGO_KEYS: case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: @@ -711,6 +758,7 @@ bool mongocrypt_ctx_setopt_masterkey_local(mongocrypt_ctx_t *ctx) { } ctx->opts.kek.kms_provider = MONGOCRYPT_KMS_PROVIDER_LOCAL; + ctx->opts.kek.kmsid = bson_strdup("local"); return true; } @@ -747,9 +795,13 @@ bool _mongocrypt_ctx_init(mongocrypt_ctx_t *ctx, _mongocrypt_ctx_opts_spec_t *op if (!ctx->opts.kek.kms_provider) { return _mongocrypt_ctx_fail_w_msg(ctx, "master key required"); } - if (!ctx->crypt->opts.use_need_kms_credentials_state - && !((int)ctx->opts.kek.kms_provider & _mongocrypt_ctx_kms_providers(ctx)->configured_providers)) { - return _mongocrypt_ctx_fail_w_msg(ctx, "requested kms provider not configured"); + mc_kms_creds_t unused; + bool is_configured = + _mongocrypt_opts_kms_providers_lookup(_mongocrypt_ctx_kms_providers(ctx), ctx->opts.kek.kmsid, &unused); + if (!ctx->crypt->opts.use_need_kms_credentials_state && !is_configured) { + mongocrypt_status_t *status = ctx->status; + CLIENT_ERR("requested kms provider not configured: `%s`", ctx->opts.kek.kmsid); + return _mongocrypt_ctx_fail(ctx); } } @@ -759,9 +811,16 @@ bool _mongocrypt_ctx_init(mongocrypt_ctx_t *ctx, _mongocrypt_ctx_opts_spec_t *op /* Check that the kms provider required by the datakey is configured. */ if (ctx->opts.kek.kms_provider) { - if (!((ctx->crypt->opts.kms_providers.need_credentials | ctx->crypt->opts.kms_providers.configured_providers) - & (int)ctx->opts.kek.kms_provider)) { - return _mongocrypt_ctx_fail_w_msg(ctx, "kms provider required by datakey is not configured"); + mc_kms_creds_t unused; + bool is_configured = + _mongocrypt_opts_kms_providers_lookup(_mongocrypt_ctx_kms_providers(ctx), ctx->opts.kek.kmsid, &unused); + bool needs = _mongocrypt_needs_credentials_for_provider(ctx->crypt, + ctx->opts.kek.kms_provider, + ctx->opts.kek.kmsid_name); + if (!is_configured && !needs) { + mongocrypt_status_t *status = ctx->status; + CLIENT_ERR("requested kms provider required by datakey is not configured: `%s`", ctx->opts.kek.kmsid); + return _mongocrypt_ctx_fail(ctx); } } @@ -1002,8 +1061,15 @@ bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t *ctx, const char *query_t if (mstr_eq_ignore_case(qt_str, mstrv_lit(MONGOCRYPT_QUERY_TYPE_EQUALITY_STR))) { ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_EQUALITY; ctx->opts.query_type.set = true; - } else if (mstr_eq_ignore_case(qt_str, mstrv_lit(MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR))) { - ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW; + } else if (mstr_eq_ignore_case(qt_str, mstrv_lit(MONGOCRYPT_QUERY_TYPE_RANGE_STR))) { + ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_RANGE; + ctx->opts.query_type.set = true; + } else if (mstr_eq_ignore_case(qt_str, mstrv_lit(MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED_STR))) { + if (ctx->crypt->opts.use_range_v2) { + _mongocrypt_ctx_fail_w_msg(ctx, "Query type 'rangePreview' is deprecated, please use 'range'"); + return false; + } + ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED; ctx->opts.query_type.set = true; } else { /* don't check if qt_str.len fits in int; we want the diagnostic output */ @@ -1021,7 +1087,8 @@ const char *_mongocrypt_index_type_to_string(mongocrypt_index_type_t val) { switch (val) { case MONGOCRYPT_INDEX_TYPE_NONE: return "None"; case MONGOCRYPT_INDEX_TYPE_EQUALITY: return "Equality"; - case MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW: return "RangePreview"; + case MONGOCRYPT_INDEX_TYPE_RANGE: return "Range"; + case MONGOCRYPT_INDEX_TYPE_RANGEPREVIEW_DEPRECATED: return "RangePreview"; default: return "Unknown"; } } @@ -1029,7 +1096,8 @@ const char *_mongocrypt_index_type_to_string(mongocrypt_index_type_t val) { const char *_mongocrypt_query_type_to_string(mongocrypt_query_type_t val) { switch (val) { case MONGOCRYPT_QUERY_TYPE_EQUALITY: return "Equality"; - case MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW: return "RangePreview"; + case MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED: return "RangePreview"; + case MONGOCRYPT_QUERY_TYPE_RANGE: return "Range"; default: return "Unknown"; } } @@ -1057,7 +1125,7 @@ bool mongocrypt_ctx_setopt_algorithm_range(mongocrypt_ctx_t *ctx, mongocrypt_bin return _mongocrypt_ctx_fail_w_msg(ctx, "invalid BSON"); } - if (!mc_RangeOpts_parse(&ctx->opts.rangeopts.value, &as_bson, ctx->status)) { + if (!mc_RangeOpts_parse(&ctx->opts.rangeopts.value, &as_bson, ctx->crypt->opts.use_range_v2, ctx->status)) { return _mongocrypt_ctx_fail(ctx); } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-dll-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-dll-private.h index e52b8cb..3debb73 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-dll-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-dll-private.h @@ -83,7 +83,14 @@ typedef struct mcr_dll_path_result { * library, or an error string. * * @note Caller must free both `retval.path` and `retval.error_string`. + * @note Returns an error if not supported on this platform. Use + * `mcr_dll_path_supported` to check before calling. */ mcr_dll_path_result mcr_dll_path(mcr_dll dll); +/** + * @brief Return true if `mcr_dll_path` is supported on this platform. + */ +bool mcr_dll_path_supported(void); + #endif // MONGOCRYPT_DLL_PRIVATE_H diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek-private.h index 8879b0f..a396b08 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek-private.h @@ -69,6 +69,7 @@ typedef struct { typedef struct { char *key_id; /* optional on parsing, required on appending. */ _mongocrypt_endpoint_t *endpoint; /* optional. */ + bool delegated; } _mongocrypt_kmip_kek_t; typedef struct { @@ -80,6 +81,9 @@ typedef struct { _mongocrypt_aws_kek_t aws; _mongocrypt_kmip_kek_t kmip; } provider; + + char *kmsid; + const char *kmsid_name; } _mongocrypt_kek_t; /* Parse a document describing a key encryption key. @@ -100,4 +104,4 @@ void _mongocrypt_kek_copy_to(const _mongocrypt_kek_t *src, _mongocrypt_kek_t *ds void _mongocrypt_kek_cleanup(_mongocrypt_kek_t *kek); -#endif /* MONGOCRYPT_KEK_PRIVATE_H */ \ No newline at end of file +#endif /* MONGOCRYPT_KEK_PRIVATE_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek.c index 11a0bd7..9329200 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek.c @@ -18,6 +18,126 @@ #include "mongocrypt-opts-private.h" #include "mongocrypt-private.h" +static bool _mongocrypt_azure_kek_parse(_mongocrypt_azure_kek_t *azure, + const char *kmsid, + const bson_t *def, + mongocrypt_status_t *status) { + if (!_mongocrypt_parse_required_endpoint(def, + "keyVaultEndpoint", + &azure->key_vault_endpoint, + NULL /* opts */, + status)) { + return false; + } + + if (!_mongocrypt_parse_required_utf8(def, "keyName", &azure->key_name, status)) { + return false; + } + + if (!_mongocrypt_parse_optional_utf8(def, "keyVersion", &azure->key_version, status)) { + return false; + } + + if (!_mongocrypt_check_allowed_fields(def, + NULL /* root */, + status, + "provider", + "keyVaultEndpoint", + "keyName", + "keyVersion")) { + return false; + } + return true; +} + +static bool _mongocrypt_gcp_kek_parse(_mongocrypt_gcp_kek_t *gcp, + const char *kmsid, + const bson_t *def, + mongocrypt_status_t *status) { + if (!_mongocrypt_parse_optional_endpoint(def, "endpoint", &gcp->endpoint, NULL /* opts */, status)) { + return false; + } + + if (!_mongocrypt_parse_required_utf8(def, "projectId", &gcp->project_id, status)) { + return false; + } + + if (!_mongocrypt_parse_required_utf8(def, "location", &gcp->location, status)) { + return false; + } + + if (!_mongocrypt_parse_required_utf8(def, "keyRing", &gcp->key_ring, status)) { + return false; + } + + if (!_mongocrypt_parse_required_utf8(def, "keyName", &gcp->key_name, status)) { + return false; + } + + if (!_mongocrypt_parse_optional_utf8(def, "keyVersion", &gcp->key_version, status)) { + return false; + } + if (!_mongocrypt_check_allowed_fields(def, + NULL, + status, + "provider", + "endpoint", + "projectId", + "location", + "keyRing", + "keyName", + "keyVersion")) { + return false; + } + return true; +} + +static bool _mongocrypt_aws_kek_parse(_mongocrypt_aws_kek_t *aws, + const char *kmsid, + const bson_t *def, + mongocrypt_status_t *status) { + if (!_mongocrypt_parse_required_utf8(def, "key", &aws->cmk, status)) { + return false; + } + if (!_mongocrypt_parse_required_utf8(def, "region", &aws->region, status)) { + return false; + } + if (!_mongocrypt_parse_optional_endpoint(def, "endpoint", &aws->endpoint, NULL /* opts */, status)) { + return false; + } + if (!_mongocrypt_check_allowed_fields(def, NULL, status, "provider", "key", "region", "endpoint")) { + return false; + } + + return true; +} + +static bool _mongocrypt_kmip_kek_parse(_mongocrypt_kmip_kek_t *kmip, + const char *kmsid, + const bson_t *def, + mongocrypt_status_t *status) { + _mongocrypt_endpoint_parse_opts_t opts = {0}; + + opts.allow_empty_subdomain = true; + if (!_mongocrypt_parse_optional_endpoint(def, "endpoint", &kmip->endpoint, &opts, status)) { + return false; + } + + if (!_mongocrypt_parse_optional_utf8(def, "keyId", &kmip->key_id, status)) { + return false; + } + + kmip->delegated = false; + if (!_mongocrypt_parse_optional_bool(def, "delegated", &kmip->delegated, status)) { + return false; + } + + if (!_mongocrypt_check_allowed_fields(def, NULL, status, "provider", "endpoint", "keyId", "delegated")) { + return false; + } + return true; +} + /* Possible documents to parse: * AWS * provider: "aws" @@ -55,116 +175,50 @@ bool _mongocrypt_kek_parse_owned(const bson_t *bson, _mongocrypt_kek_t *kek, mon goto done; } - if (0 == strcmp(kms_provider, "aws")) { - kek->kms_provider = MONGOCRYPT_KMS_PROVIDER_AWS; - if (!_mongocrypt_parse_required_utf8(bson, "key", &kek->provider.aws.cmk, status)) { - goto done; - } - if (!_mongocrypt_parse_required_utf8(bson, "region", &kek->provider.aws.region, status)) { - goto done; - } - if (!_mongocrypt_parse_optional_endpoint(bson, - "endpoint", - &kek->provider.aws.endpoint, - NULL /* opts */, - status)) { - goto done; - } - if (!_mongocrypt_check_allowed_fields(bson, NULL, status, "provider", "key", "region", "endpoint")) { - goto done; - } - } else if (0 == strcmp(kms_provider, "local")) { - kek->kms_provider = MONGOCRYPT_KMS_PROVIDER_LOCAL; - if (!_mongocrypt_check_allowed_fields(bson, NULL, status, "provider")) { - goto done; - } - } else if (0 == strcmp(kms_provider, "azure")) { - kek->kms_provider = MONGOCRYPT_KMS_PROVIDER_AZURE; - if (!_mongocrypt_parse_required_endpoint(bson, - "keyVaultEndpoint", - &kek->provider.azure.key_vault_endpoint, - NULL /* opts */, - status)) { - goto done; - } - - if (!_mongocrypt_parse_required_utf8(bson, "keyName", &kek->provider.azure.key_name, status)) { - goto done; - } - - if (!_mongocrypt_parse_optional_utf8(bson, "keyVersion", &kek->provider.azure.key_version, status)) { - goto done; - } - - if (!_mongocrypt_check_allowed_fields(bson, - NULL, - status, - "provider", - "keyVaultEndpoint", - "keyName", - "keyVersion")) { - goto done; - } - } else if (0 == strcmp(kms_provider, "gcp")) { - kek->kms_provider = MONGOCRYPT_KMS_PROVIDER_GCP; - if (!_mongocrypt_parse_optional_endpoint(bson, - "endpoint", - &kek->provider.gcp.endpoint, - NULL /* opts */, - status)) { - goto done; - } - - if (!_mongocrypt_parse_required_utf8(bson, "projectId", &kek->provider.gcp.project_id, status)) { - goto done; - } - - if (!_mongocrypt_parse_required_utf8(bson, "location", &kek->provider.gcp.location, status)) { - goto done; - } - - if (!_mongocrypt_parse_required_utf8(bson, "keyRing", &kek->provider.gcp.key_ring, status)) { - goto done; - } + kek->kmsid = bson_strdup(kms_provider); - if (!_mongocrypt_parse_required_utf8(bson, "keyName", &kek->provider.gcp.key_name, status)) { - goto done; - } + _mongocrypt_kms_provider_t type; + if (!mc_kmsid_parse(kek->kmsid, &type, &kek->kmsid_name, status)) { + goto done; + } - if (!_mongocrypt_parse_optional_utf8(bson, "keyVersion", &kek->provider.gcp.key_version, status)) { + kek->kms_provider = type; + switch (type) { + default: + case MONGOCRYPT_KMS_PROVIDER_NONE: { + CLIENT_ERR("Unexpected parsing KMS type: none"); + goto done; + } + case MONGOCRYPT_KMS_PROVIDER_AWS: { + if (!_mongocrypt_aws_kek_parse(&kek->provider.aws, kek->kmsid, bson, status)) { goto done; } - if (!_mongocrypt_check_allowed_fields(bson, - NULL, - status, - "provider", - "endpoint", - "projectId", - "location", - "keyRing", - "keyName", - "keyVersion")) { + break; + } + case MONGOCRYPT_KMS_PROVIDER_LOCAL: { + if (!_mongocrypt_check_allowed_fields(bson, NULL, status, "provider")) { goto done; } - } else if (0 == strcmp(kms_provider, "kmip")) { - kek->kms_provider = MONGOCRYPT_KMS_PROVIDER_KMIP; - _mongocrypt_endpoint_parse_opts_t opts = {0}; - - opts.allow_empty_subdomain = true; - if (!_mongocrypt_parse_optional_endpoint(bson, "endpoint", &kek->provider.kmip.endpoint, &opts, status)) { + break; + } + case MONGOCRYPT_KMS_PROVIDER_AZURE: { + if (!_mongocrypt_azure_kek_parse(&kek->provider.azure, kek->kmsid, bson, status)) { goto done; } - - if (!_mongocrypt_parse_optional_utf8(bson, "keyId", &kek->provider.kmip.key_id, status)) { + break; + } + case MONGOCRYPT_KMS_PROVIDER_GCP: { + if (!_mongocrypt_gcp_kek_parse(&kek->provider.gcp, kek->kmsid, bson, status)) { goto done; } - - if (!_mongocrypt_check_allowed_fields(bson, NULL, status, "provider", "endpoint", "keyId")) { + break; + } + case MONGOCRYPT_KMS_PROVIDER_KMIP: { + if (!_mongocrypt_kmip_kek_parse(&kek->provider.kmip, kek->kmsid, bson, status)) { goto done; } - } else { - CLIENT_ERR("unrecognized KMS provider: %s", kms_provider); - goto done; + break; + } } ret = true; @@ -177,24 +231,22 @@ bool _mongocrypt_kek_append(const _mongocrypt_kek_t *kek, bson_t *bson, mongocry BSON_ASSERT_PARAM(kek); BSON_ASSERT_PARAM(bson); + BSON_APPEND_UTF8(bson, "provider", kek->kmsid); if (kek->kms_provider == MONGOCRYPT_KMS_PROVIDER_AWS) { - BSON_APPEND_UTF8(bson, "provider", "aws"); BSON_APPEND_UTF8(bson, "region", kek->provider.aws.region); BSON_APPEND_UTF8(bson, "key", kek->provider.aws.cmk); if (kek->provider.aws.endpoint) { BSON_APPEND_UTF8(bson, "endpoint", kek->provider.aws.endpoint->host_and_port); } } else if (kek->kms_provider == MONGOCRYPT_KMS_PROVIDER_LOCAL) { - BSON_APPEND_UTF8(bson, "provider", "local"); + // Only `provider` is needed. } else if (kek->kms_provider == MONGOCRYPT_KMS_PROVIDER_AZURE) { - BSON_APPEND_UTF8(bson, "provider", "azure"); BSON_APPEND_UTF8(bson, "keyVaultEndpoint", kek->provider.azure.key_vault_endpoint->host_and_port); BSON_APPEND_UTF8(bson, "keyName", kek->provider.azure.key_name); if (kek->provider.azure.key_version) { BSON_APPEND_UTF8(bson, "keyVersion", kek->provider.azure.key_version); } } else if (kek->kms_provider == MONGOCRYPT_KMS_PROVIDER_GCP) { - BSON_APPEND_UTF8(bson, "provider", "gcp"); BSON_APPEND_UTF8(bson, "projectId", kek->provider.gcp.project_id); BSON_APPEND_UTF8(bson, "location", kek->provider.gcp.location); BSON_APPEND_UTF8(bson, "keyRing", kek->provider.gcp.key_ring); @@ -206,11 +258,14 @@ bool _mongocrypt_kek_append(const _mongocrypt_kek_t *kek, bson_t *bson, mongocry BSON_APPEND_UTF8(bson, "endpoint", kek->provider.gcp.endpoint->host_and_port); } } else if (kek->kms_provider == MONGOCRYPT_KMS_PROVIDER_KMIP) { - BSON_APPEND_UTF8(bson, "provider", "kmip"); if (kek->provider.kmip.endpoint) { BSON_APPEND_UTF8(bson, "endpoint", kek->provider.kmip.endpoint->host_and_port); } + if (kek->provider.kmip.delegated) { + BSON_APPEND_BOOL(bson, "delegated", kek->provider.kmip.delegated); + } + /* "keyId" is required in the final data key document for the "kmip" KMS * provider. It may be set from the "kmip.keyId" in the BSON document set * in mongocrypt_ctx_setopt_key_encryption_key, Otherwise, libmongocrypt @@ -249,11 +304,13 @@ void _mongocrypt_kek_copy_to(const _mongocrypt_kek_t *src, _mongocrypt_kek_t *ds } else if (src->kms_provider == MONGOCRYPT_KMS_PROVIDER_KMIP) { dst->provider.kmip.endpoint = _mongocrypt_endpoint_copy(src->provider.kmip.endpoint); dst->provider.kmip.key_id = bson_strdup(src->provider.kmip.key_id); + dst->provider.kmip.delegated = src->provider.kmip.delegated; } else { BSON_ASSERT(src->kms_provider == MONGOCRYPT_KMS_PROVIDER_NONE || src->kms_provider == MONGOCRYPT_KMS_PROVIDER_LOCAL); } dst->kms_provider = src->kms_provider; + dst->kmsid = bson_strdup(src->kmsid); } void _mongocrypt_kek_cleanup(_mongocrypt_kek_t *kek) { @@ -283,5 +340,6 @@ void _mongocrypt_kek_cleanup(_mongocrypt_kek_t *kek) { BSON_ASSERT(kek->kms_provider == MONGOCRYPT_KMS_PROVIDER_NONE || kek->kms_provider == MONGOCRYPT_KMS_PROVIDER_LOCAL); } + bson_free(kek->kmsid); return; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker-private.h index b4ca3b7..630dd9c 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker-private.h @@ -87,11 +87,7 @@ typedef struct _key_returned_t { struct _key_returned_t *next; } key_returned_t; -typedef struct _auth_request_t { - mongocrypt_kms_ctx_t kms; - bool returned; - bool initialized; -} auth_request_t; +typedef struct _mc_mapof_kmsid_to_authrequest_t mc_mapof_kmsid_to_authrequest_t; typedef struct { key_broker_state_t state; @@ -109,8 +105,7 @@ typedef struct { mongocrypt_t *crypt; key_returned_t *decryptor_iter; - auth_request_t auth_request_azure; - auth_request_t auth_request_gcp; + mc_mapof_kmsid_to_authrequest_t *auth_requests; } _mongocrypt_key_broker_t; void _mongocrypt_key_broker_init(_mongocrypt_key_broker_t *kb, mongocrypt_t *crypt); diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c index 77ce882..3707be4 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c @@ -14,9 +14,87 @@ * limitations under the License. */ +#include "mc-array-private.h" #include "mongocrypt-key-broker-private.h" #include "mongocrypt-private.h" +typedef struct _auth_request_t { + mongocrypt_kms_ctx_t kms; + bool returned; + char *kmsid; +} auth_request_t; + +auth_request_t *auth_request_new() { + return bson_malloc0(sizeof(auth_request_t)); +} + +void auth_request_destroy(auth_request_t *ar) { + if (!ar) { + return; + } + _mongocrypt_kms_ctx_cleanup(&ar->kms); + bson_free(ar->kmsid); + bson_free(ar); +} + +struct _mc_mapof_kmsid_to_authrequest_t { + mc_array_t entries; +}; + +mc_mapof_kmsid_to_authrequest_t *mc_mapof_kmsid_to_authrequest_new(void) { + mc_mapof_kmsid_to_authrequest_t *k2a = bson_malloc0(sizeof(mc_mapof_kmsid_to_authrequest_t)); + _mc_array_init(&k2a->entries, sizeof(auth_request_t *)); + return k2a; +} + +void mc_mapof_kmsid_to_authrequest_destroy(mc_mapof_kmsid_to_authrequest_t *k2a) { + if (!k2a) { + return; + } + for (size_t i = 0; i < k2a->entries.len; i++) { + auth_request_t *ar = _mc_array_index(&k2a->entries, auth_request_t *, i); + auth_request_destroy(ar); + } + _mc_array_destroy(&k2a->entries); + bson_free(k2a); +} + +bool mc_mapof_kmsid_to_authrequest_has(const mc_mapof_kmsid_to_authrequest_t *k2a, const char *kmsid) { + BSON_ASSERT_PARAM(k2a); + BSON_ASSERT_PARAM(kmsid); + for (size_t i = 0; i < k2a->entries.len; i++) { + auth_request_t *ar = _mc_array_index(&k2a->entries, auth_request_t *, i); + if (0 == strcmp(ar->kmsid, kmsid)) { + return true; + } + } + return false; +} + +size_t mc_mapof_kmsid_to_authrequest_len(const mc_mapof_kmsid_to_authrequest_t *k2a) { + BSON_ASSERT_PARAM(k2a); + return k2a->entries.len; +} + +bool mc_mapof_kmsid_to_authrequest_empty(const mc_mapof_kmsid_to_authrequest_t *k2a) { + BSON_ASSERT_PARAM(k2a); + return k2a->entries.len == 0; +} + +// `mc_mapof_kmsid_to_authrequest_put` moves `to_put` into the map and takes ownership of `to_put`. +// No checking is done to prohibit duplicate entries. +void mc_mapof_kmsid_to_authrequest_put(mc_mapof_kmsid_to_authrequest_t *k2a, auth_request_t *to_put) { + BSON_ASSERT_PARAM(k2a); + + _mc_array_append_val(&k2a->entries, to_put); +} + +auth_request_t *mc_mapof_kmsid_to_authrequest_at(mc_mapof_kmsid_to_authrequest_t *k2a, size_t i) { + BSON_ASSERT_PARAM(k2a); + + return _mc_array_index(&k2a->entries, auth_request_t *, i); +} + void _mongocrypt_key_broker_init(_mongocrypt_key_broker_t *kb, mongocrypt_t *crypt) { BSON_ASSERT_PARAM(kb); BSON_ASSERT_PARAM(crypt); @@ -25,6 +103,7 @@ void _mongocrypt_key_broker_init(_mongocrypt_key_broker_t *kb, mongocrypt_t *cry kb->crypt = crypt; kb->state = KB_REQUESTING; kb->status = mongocrypt_status_new(); + kb->auth_requests = mc_mapof_kmsid_to_authrequest_new(); } /* @@ -481,8 +560,12 @@ bool _mongocrypt_key_broker_add_doc(_mongocrypt_key_broker_t *kb, /* Check that the returned key doc's provider matches. */ kek_provider = key_doc->kek.kms_provider; - if (0 == ((int)kek_provider & kms_providers->configured_providers)) { - _key_broker_fail_w_msg(kb, "client not configured with KMS provider necessary to decrypt"); + + mc_kms_creds_t kc; + if (!_mongocrypt_opts_kms_providers_lookup(kms_providers, key_doc->kek.kmsid, &kc)) { + mongocrypt_status_t *status = kb->status; + CLIENT_ERR("KMS provider `%s` is not configured", key_doc->kek.kmsid); + _key_broker_fail(kb); goto done; } @@ -490,8 +573,9 @@ bool _mongocrypt_key_broker_add_doc(_mongocrypt_key_broker_t *kb, * HTTP KMS request. */ BSON_ASSERT(kb->crypt); if (kek_provider == MONGOCRYPT_KMS_PROVIDER_LOCAL) { + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_LOCAL); if (!_mongocrypt_unwrap_key(kb->crypt->crypto, - &kms_providers->local.key, + &kc.value.local.key, &key_returned->doc->key_material, &key_returned->decrypted_key_material, kb->status)) { @@ -506,38 +590,45 @@ bool _mongocrypt_key_broker_add_doc(_mongocrypt_key_broker_t *kb, if (!_mongocrypt_kms_ctx_init_aws_decrypt(&key_returned->kms, kms_providers, key_doc, - &kb->crypt->log, - kb->crypt->crypto)) { + kb->crypt->crypto, + key_doc->kek.kmsid, + &kb->crypt->log)) { mongocrypt_kms_ctx_status(&key_returned->kms, kb->status); _key_broker_fail(kb); goto done; } } else if (kek_provider == MONGOCRYPT_KMS_PROVIDER_AZURE) { - if (kms_providers->azure.access_token) { - access_token = bson_strdup(kms_providers->azure.access_token); + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_AZURE); + if (kc.value.azure.access_token) { + access_token = bson_strdup(kc.value.azure.access_token); } else { - access_token = _mongocrypt_cache_oauth_get(kb->crypt->cache_oauth_azure); + access_token = mc_mapof_kmsid_to_token_get_token(kb->crypt->cache_oauth, key_doc->kek.kmsid); } if (!access_token) { key_returned->needs_auth = true; /* Create an oauth request if one does not exist. */ - if (!kb->auth_request_azure.initialized) { - if (!_mongocrypt_kms_ctx_init_azure_auth(&kb->auth_request_azure.kms, - &kb->crypt->log, - kms_providers, + if (!mc_mapof_kmsid_to_authrequest_has(kb->auth_requests, key_doc->kek.kmsid)) { + auth_request_t *ar = auth_request_new(); + if (!_mongocrypt_kms_ctx_init_azure_auth(&ar->kms, + &kc, /* The key vault endpoint is used to determine the scope. */ - key_doc->kek.provider.azure.key_vault_endpoint)) { - mongocrypt_kms_ctx_status(&kb->auth_request_azure.kms, kb->status); + key_doc->kek.provider.azure.key_vault_endpoint, + key_doc->kek.kmsid, + &kb->crypt->log)) { + mongocrypt_kms_ctx_status(&ar->kms, kb->status); _key_broker_fail(kb); + auth_request_destroy(ar); goto done; } - kb->auth_request_azure.initialized = true; + ar->kmsid = bson_strdup(key_doc->kek.kmsid); + mc_mapof_kmsid_to_authrequest_put(kb->auth_requests, ar); } } else { if (!_mongocrypt_kms_ctx_init_azure_unwrapkey(&key_returned->kms, kms_providers, access_token, key_doc, + key_returned->doc->kek.kmsid, &kb->crypt->log)) { mongocrypt_kms_ctx_status(&key_returned->kms, kb->status); _key_broker_fail(kb); @@ -545,31 +636,37 @@ bool _mongocrypt_key_broker_add_doc(_mongocrypt_key_broker_t *kb, } } } else if (kek_provider == MONGOCRYPT_KMS_PROVIDER_GCP) { - if (NULL != kms_providers->gcp.access_token) { - access_token = bson_strdup(kms_providers->gcp.access_token); + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_GCP); + if (NULL != kc.value.gcp.access_token) { + access_token = bson_strdup(kc.value.gcp.access_token); } else { - access_token = _mongocrypt_cache_oauth_get(kb->crypt->cache_oauth_gcp); + access_token = mc_mapof_kmsid_to_token_get_token(kb->crypt->cache_oauth, key_doc->kek.kmsid); } if (!access_token) { key_returned->needs_auth = true; /* Create an oauth request if one does not exist. */ - if (!kb->auth_request_gcp.initialized) { - if (!_mongocrypt_kms_ctx_init_gcp_auth(&kb->auth_request_gcp.kms, - &kb->crypt->log, + if (!mc_mapof_kmsid_to_authrequest_has(kb->auth_requests, key_doc->kek.kmsid)) { + auth_request_t *ar = auth_request_new(); + if (!_mongocrypt_kms_ctx_init_gcp_auth(&ar->kms, &kb->crypt->opts, - kms_providers, - key_doc->kek.provider.gcp.endpoint)) { - mongocrypt_kms_ctx_status(&kb->auth_request_gcp.kms, kb->status); + &kc, + key_doc->kek.provider.gcp.endpoint, + key_doc->kek.kmsid, + &kb->crypt->log)) { + mongocrypt_kms_ctx_status(&ar->kms, kb->status); _key_broker_fail(kb); + auth_request_destroy(ar); goto done; } - kb->auth_request_gcp.initialized = true; + ar->kmsid = bson_strdup(key_doc->kek.kmsid); + mc_mapof_kmsid_to_authrequest_put(kb->auth_requests, ar); } } else { if (!_mongocrypt_kms_ctx_init_gcp_decrypt(&key_returned->kms, kms_providers, access_token, key_doc, + key_returned->doc->kek.kmsid, &kb->crypt->log)) { mongocrypt_kms_ctx_status(&key_returned->kms, kb->status); _key_broker_fail(kb); @@ -577,6 +674,7 @@ bool _mongocrypt_key_broker_add_doc(_mongocrypt_key_broker_t *kb, } } } else if (kek_provider == MONGOCRYPT_KMS_PROVIDER_KMIP) { + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_KMIP); char *unique_identifier; _mongocrypt_endpoint_t *endpoint; @@ -589,17 +687,33 @@ bool _mongocrypt_key_broker_add_doc(_mongocrypt_key_broker_t *kb, if (key_returned->doc->kek.provider.kmip.endpoint) { endpoint = key_returned->doc->kek.provider.kmip.endpoint; - } else if (kms_providers->kmip.endpoint) { - endpoint = kms_providers->kmip.endpoint; + } else if (kc.value.kmip.endpoint) { + endpoint = kc.value.kmip.endpoint; } else { _key_broker_fail_w_msg(kb, "endpoint not set for KMIP request"); goto done; } - if (!_mongocrypt_kms_ctx_init_kmip_get(&key_returned->kms, endpoint, unique_identifier, &kb->crypt->log)) { - mongocrypt_kms_ctx_status(&key_returned->kms, kb->status); - _key_broker_fail(kb); - goto done; + if (key_returned->doc->kek.provider.kmip.delegated) { + if (!_mongocrypt_kms_ctx_init_kmip_decrypt(&key_returned->kms, + endpoint, + key_doc->kek.kmsid, + key_doc, + &kb->crypt->log)) { + mongocrypt_kms_ctx_status(&key_returned->kms, kb->status); + _key_broker_fail(kb); + goto done; + } + } else { + if (!_mongocrypt_kms_ctx_init_kmip_get(&key_returned->kms, + endpoint, + unique_identifier, + key_doc->kek.kmsid, + &kb->crypt->log)) { + mongocrypt_kms_ctx_status(&key_returned->kms, kb->status); + _key_broker_fail(kb); + goto done; + } } } else { _key_broker_fail_w_msg(kb, "unrecognized kms provider"); @@ -683,20 +797,21 @@ mongocrypt_kms_ctx_t *_mongocrypt_key_broker_next_kms(_mongocrypt_key_broker_t * } if (kb->state == KB_AUTHENTICATING) { - if (!kb->auth_request_azure.initialized && !kb->auth_request_gcp.initialized) { + if (mc_mapof_kmsid_to_authrequest_empty(kb->auth_requests)) { _key_broker_fail_w_msg(kb, "unexpected, attempting to authenticate but " "KMS request not initialized"); return NULL; } - if (kb->auth_request_azure.initialized && !kb->auth_request_azure.returned) { - kb->auth_request_azure.returned = true; - return &kb->auth_request_azure.kms; - } - if (kb->auth_request_gcp.initialized && !kb->auth_request_gcp.returned) { - kb->auth_request_gcp.returned = true; - return &kb->auth_request_gcp.kms; + // Return the first not-yet-returned auth request. + for (size_t i = 0; i < mc_mapof_kmsid_to_authrequest_len(kb->auth_requests); i++) { + auth_request_t *ar = mc_mapof_kmsid_to_authrequest_at(kb->auth_requests, i); + if (ar->returned) { + continue; + } + ar->returned = true; + return &ar->kms; } return NULL; @@ -731,29 +846,19 @@ bool _mongocrypt_key_broker_kms_done(_mongocrypt_key_broker_t *kb, _mongocrypt_o bson_t oauth_response; _mongocrypt_buffer_t oauth_response_buf; - if (kb->auth_request_azure.initialized) { - if (!_mongocrypt_kms_ctx_result(&kb->auth_request_azure.kms, &oauth_response_buf)) { - mongocrypt_kms_ctx_status(&kb->auth_request_azure.kms, kb->status); - return _key_broker_fail(kb); - } - - /* Cache returned tokens. */ - BSON_ASSERT(_mongocrypt_buffer_to_bson(&oauth_response_buf, &oauth_response)); - if (!_mongocrypt_cache_oauth_add(kb->crypt->cache_oauth_azure, &oauth_response, kb->status)) { - return false; - } - } + // Apply tokens from oauth responses to oauth token cache. + for (size_t i = 0; i < mc_mapof_kmsid_to_authrequest_len(kb->auth_requests); i++) { + auth_request_t *ar = mc_mapof_kmsid_to_authrequest_at(kb->auth_requests, i); - if (kb->auth_request_gcp.initialized) { - if (!_mongocrypt_kms_ctx_result(&kb->auth_request_gcp.kms, &oauth_response_buf)) { - mongocrypt_kms_ctx_status(&kb->auth_request_gcp.kms, kb->status); + if (!_mongocrypt_kms_ctx_result(&ar->kms, &oauth_response_buf)) { + mongocrypt_kms_ctx_status(&ar->kms, kb->status); return _key_broker_fail(kb); } /* Cache returned tokens. */ BSON_ASSERT(_mongocrypt_buffer_to_bson(&oauth_response_buf, &oauth_response)); - if (!_mongocrypt_cache_oauth_add(kb->crypt->cache_oauth_gcp, &oauth_response, kb->status)) { - return false; + if (!mc_mapof_kmsid_to_token_add_response(kb->crypt->cache_oauth, ar->kmsid, &oauth_response, kb->status)) { + return _key_broker_fail(kb); } } @@ -765,11 +870,20 @@ bool _mongocrypt_key_broker_kms_done(_mongocrypt_key_broker_t *kb, _mongocrypt_o continue; } + mc_kms_creds_t kc; + if (!_mongocrypt_opts_kms_providers_lookup(kms_providers, key_returned->doc->kek.kmsid, &kc)) { + mongocrypt_status_t *status = kb->status; + CLIENT_ERR("KMS provider `%s` is not configured", key_returned->doc->kek.kmsid); + return _key_broker_fail(kb); + } + if (key_returned->doc->kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_AZURE) { - if (kms_providers->azure.access_token) { - access_token = bson_strdup(kms_providers->azure.access_token); + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_AZURE); + if (kc.value.azure.access_token) { + access_token = bson_strdup(kc.value.azure.access_token); } else { - access_token = _mongocrypt_cache_oauth_get(kb->crypt->cache_oauth_azure); + access_token = + mc_mapof_kmsid_to_token_get_token(kb->crypt->cache_oauth, key_returned->doc->kek.kmsid); } if (!access_token) { @@ -780,6 +894,7 @@ bool _mongocrypt_key_broker_kms_done(_mongocrypt_key_broker_t *kb, _mongocrypt_o kms_providers, access_token, key_returned->doc, + key_returned->doc->kek.kmsid, &kb->crypt->log)) { mongocrypt_kms_ctx_status(&key_returned->kms, kb->status); bson_free(access_token); @@ -789,10 +904,12 @@ bool _mongocrypt_key_broker_kms_done(_mongocrypt_key_broker_t *kb, _mongocrypt_o key_returned->needs_auth = false; bson_free(access_token); } else if (key_returned->doc->kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_GCP) { - if (NULL != kms_providers->gcp.access_token) { - access_token = bson_strdup(kms_providers->gcp.access_token); + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_GCP); + if (kc.value.gcp.access_token) { + access_token = bson_strdup(kc.value.gcp.access_token); } else { - access_token = _mongocrypt_cache_oauth_get(kb->crypt->cache_oauth_gcp); + access_token = + mc_mapof_kmsid_to_token_get_token(kb->crypt->cache_oauth, key_returned->doc->kek.kmsid); } if (!access_token) { @@ -803,6 +920,7 @@ bool _mongocrypt_key_broker_kms_done(_mongocrypt_key_broker_t *kb, _mongocrypt_o kms_providers, access_token, key_returned->doc, + key_returned->doc->kek.kmsid, &kb->crypt->log)) { mongocrypt_kms_ctx_status(&key_returned->kms, kb->status); bson_free(access_token); @@ -850,11 +968,16 @@ bool _mongocrypt_key_broker_kms_done(_mongocrypt_key_broker_t *kb, _mongocrypt_o return _key_broker_fail(kb); } - if (!_mongocrypt_unwrap_key(kb->crypt->crypto, - &kek, - &key_returned->doc->key_material, - &key_returned->decrypted_key_material, - kb->status)) { + if (key_returned->doc->kek.provider.kmip.delegated) { + if (!_mongocrypt_kms_ctx_result(&key_returned->kms, &key_returned->decrypted_key_material)) { + mongocrypt_kms_ctx_status(&key_returned->kms, kb->status); + return _key_broker_fail(kb); + } + } else if (!_mongocrypt_unwrap_key(kb->crypt->crypto, + &kek, + &key_returned->doc->key_material, + &key_returned->decrypted_key_material, + kb->status)) { _key_broker_fail(kb); _mongocrypt_buffer_cleanup(&kek); return false; @@ -1008,8 +1131,7 @@ void _mongocrypt_key_broker_cleanup(_mongocrypt_key_broker_t *kb) { _destroy_keys_returned(kb->keys_returned); _destroy_keys_returned(kb->keys_cached); _destroy_key_requests(kb->key_requests); - _mongocrypt_kms_ctx_cleanup(&kb->auth_request_azure.kms); - _mongocrypt_kms_ctx_cleanup(&kb->auth_request_gcp.kms); + mc_mapof_kmsid_to_authrequest_destroy(kb->auth_requests); } void _mongocrypt_key_broker_add_test_key(_mongocrypt_key_broker_t *kb, const _mongocrypt_buffer_t *key_id) { diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key.c index 25421d9..cc2e44f 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key.c @@ -127,7 +127,7 @@ bool _mongocrypt_key_alt_name_from_iter(const bson_iter_t *iter_in, /* Takes ownership of all fields. */ bool _mongocrypt_key_parse_owned(const bson_t *bson, _mongocrypt_key_doc_t *out, mongocrypt_status_t *status) { - bson_iter_t iter; + bson_iter_t iter = {0}; bool has_id = false, has_key_material = false, has_status = false, has_creation_date = false, has_update_date = false, has_master_key = false; diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx-private.h index e1b66f1..4b465fd 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx-private.h @@ -23,6 +23,7 @@ #include "mongocrypt-compat.h" #include "mongocrypt-crypto-private.h" #include "mongocrypt-endpoint-private.h" +#include "mongocrypt-key-private.h" #include "mongocrypt-opts-private.h" #include "mongocrypt.h" @@ -39,7 +40,10 @@ typedef enum { MONGOCRYPT_KMS_GCP_DECRYPT, MONGOCRYPT_KMS_KMIP_REGISTER, MONGOCRYPT_KMS_KMIP_ACTIVATE, - MONGOCRYPT_KMS_KMIP_GET + MONGOCRYPT_KMS_KMIP_GET, + MONGOCRYPT_KMS_KMIP_CREATE, + MONGOCRYPT_KMS_KMIP_ENCRYPT, + MONGOCRYPT_KMS_KMIP_DECRYPT, } _kms_request_type_t; struct _mongocrypt_kms_ctx_t { @@ -51,76 +55,107 @@ struct _mongocrypt_kms_ctx_t { _mongocrypt_buffer_t result; char *endpoint; _mongocrypt_log_t *log; + char *kmsid; }; bool _mongocrypt_kms_ctx_init_aws_decrypt(mongocrypt_kms_ctx_t *kms, _mongocrypt_opts_kms_providers_t *kms_providers, _mongocrypt_key_doc_t *key, - _mongocrypt_log_t *log, - _mongocrypt_crypto_t *crypto) MONGOCRYPT_WARN_UNUSED_RESULT; + _mongocrypt_crypto_t *crypto, + const char *kmsid, + _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_init_aws_encrypt(mongocrypt_kms_ctx_t *kms, _mongocrypt_opts_kms_providers_t *kms_providers, struct __mongocrypt_ctx_opts_t *ctx_opts, _mongocrypt_buffer_t *decrypted_key_material, - _mongocrypt_log_t *log, - _mongocrypt_crypto_t *crypto) MONGOCRYPT_WARN_UNUSED_RESULT; + _mongocrypt_crypto_t *crypto, + const char *kmsid, + _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_result(mongocrypt_kms_ctx_t *kms, _mongocrypt_buffer_t *out) MONGOCRYPT_WARN_UNUSED_RESULT; void _mongocrypt_kms_ctx_cleanup(mongocrypt_kms_ctx_t *kms); bool _mongocrypt_kms_ctx_init_azure_auth(mongocrypt_kms_ctx_t *kms, - _mongocrypt_log_t *log, - _mongocrypt_opts_kms_providers_t *kms_providers, - _mongocrypt_endpoint_t *key_vault_endpoint) MONGOCRYPT_WARN_UNUSED_RESULT; + const mc_kms_creds_t *kc, + _mongocrypt_endpoint_t *key_vault_endpoint, + const char *kmsid, + _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_init_azure_wrapkey(mongocrypt_kms_ctx_t *kms, - _mongocrypt_log_t *log, _mongocrypt_opts_kms_providers_t *kms_providers, struct __mongocrypt_ctx_opts_t *ctx_opts, const char *access_token, - _mongocrypt_buffer_t *plaintext_key_material) MONGOCRYPT_WARN_UNUSED_RESULT; + _mongocrypt_buffer_t *plaintext_key_material, + const char *kmsid, + _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_init_azure_unwrapkey(mongocrypt_kms_ctx_t *kms, _mongocrypt_opts_kms_providers_t *kms_providers, const char *access_token, _mongocrypt_key_doc_t *key, + const char *kmsid, _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_init_gcp_auth(mongocrypt_kms_ctx_t *kms, - _mongocrypt_log_t *log, _mongocrypt_opts_t *crypt_opts, - _mongocrypt_opts_kms_providers_t *kms_providers, - _mongocrypt_endpoint_t *kms_endpoint) MONGOCRYPT_WARN_UNUSED_RESULT; + const mc_kms_creds_t *kc, + _mongocrypt_endpoint_t *kms_endpoint, + const char *kmsid, + _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_init_gcp_encrypt(mongocrypt_kms_ctx_t *kms, - _mongocrypt_log_t *log, _mongocrypt_opts_kms_providers_t *kms_providers, struct __mongocrypt_ctx_opts_t *ctx_opts, const char *access_token, - _mongocrypt_buffer_t *plaintext_key_material) MONGOCRYPT_WARN_UNUSED_RESULT; + _mongocrypt_buffer_t *plaintext_key_material, + const char *kmsid, + _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_init_gcp_decrypt(mongocrypt_kms_ctx_t *kms, _mongocrypt_opts_kms_providers_t *kms_providers, const char *access_token, _mongocrypt_key_doc_t *key, + const char *kmsid, _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_init_kmip_register(mongocrypt_kms_ctx_t *kms, const _mongocrypt_endpoint_t *endpoint, const uint8_t *secretdata, uint32_t secretdata_len, + + const char *kmsid, _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_init_kmip_activate(mongocrypt_kms_ctx_t *kms, const _mongocrypt_endpoint_t *endpoint, const char *unique_identifier, + const char *kmsid, _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; bool _mongocrypt_kms_ctx_init_kmip_get(mongocrypt_kms_ctx_t *kms, const _mongocrypt_endpoint_t *endpoint, const char *unique_identifier, + const char *kmsid, _mongocrypt_log_t *log) MONGOCRYPT_WARN_UNUSED_RESULT; +bool _mongocrypt_kms_ctx_init_kmip_create(mongocrypt_kms_ctx_t *kms, + const _mongocrypt_endpoint_t *endpoint, + const char *kmsid, + _mongocrypt_log_t *log); + +bool _mongocrypt_kms_ctx_init_kmip_encrypt(mongocrypt_kms_ctx_t *kms, + const _mongocrypt_endpoint_t *endpoint, + const char *unique_identifier, + const char *kmsid, + _mongocrypt_buffer_t *plaintext, + _mongocrypt_log_t *log); + +bool _mongocrypt_kms_ctx_init_kmip_decrypt(mongocrypt_kms_ctx_t *kms, + const _mongocrypt_endpoint_t *endpoint, + const char *kmsid, + _mongocrypt_key_doc_t *key, + _mongocrypt_log_t *log); + #endif /* MONGOCRYPT_KMX_CTX_PRIVATE_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c index 6886b55..d15a03e 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c @@ -14,10 +14,14 @@ * limitations under the License. */ +#include "kms_message/kms_kmip_request.h" #include "mongocrypt-binary-private.h" #include "mongocrypt-buffer-private.h" +#include "mongocrypt-crypto-private.h" #include "mongocrypt-ctx-private.h" +#include "mongocrypt-endpoint-private.h" #include "mongocrypt-kms-ctx-private.h" +#include "mongocrypt-log-private.h" #include "mongocrypt-opts-private.h" #include "mongocrypt-private.h" #include "mongocrypt-status-private.h" @@ -118,11 +122,16 @@ _set_kms_crypto_hooks(_mongocrypt_crypto_t *crypto, ctx_with_status_t *ctx_with_ static bool is_kms(_kms_request_type_t kms_type) { return kms_type == MONGOCRYPT_KMS_KMIP_REGISTER || kms_type == MONGOCRYPT_KMS_KMIP_ACTIVATE - || kms_type == MONGOCRYPT_KMS_KMIP_GET; + || kms_type == MONGOCRYPT_KMS_KMIP_GET || kms_type == MONGOCRYPT_KMS_KMIP_ENCRYPT + || kms_type == MONGOCRYPT_KMS_KMIP_DECRYPT || kms_type == MONGOCRYPT_KMS_KMIP_CREATE; } -static void _init_common(mongocrypt_kms_ctx_t *kms, _mongocrypt_log_t *log, _kms_request_type_t kms_type) { +static void +_init_common(mongocrypt_kms_ctx_t *kms, _mongocrypt_log_t *log, _kms_request_type_t kms_type, const char *kmsid) { BSON_ASSERT_PARAM(kms); + BSON_ASSERT_PARAM(kmsid); + + kms->kmsid = bson_strdup(kmsid); if (is_kms(kms_type)) { kms->parser = kms_kmip_response_parser_new(NULL /* reserved */); @@ -138,8 +147,9 @@ static void _init_common(mongocrypt_kms_ctx_t *kms, _mongocrypt_log_t *log, _kms bool _mongocrypt_kms_ctx_init_aws_decrypt(mongocrypt_kms_ctx_t *kms, _mongocrypt_opts_kms_providers_t *kms_providers, _mongocrypt_key_doc_t *key, - _mongocrypt_log_t *log, - _mongocrypt_crypto_t *crypto) { + _mongocrypt_crypto_t *crypto, + const char *kmsid, + _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms); BSON_ASSERT_PARAM(key); BSON_ASSERT_PARAM(kms_providers); @@ -150,7 +160,7 @@ bool _mongocrypt_kms_ctx_init_aws_decrypt(mongocrypt_kms_ctx_t *kms, ctx_with_status_t ctx_with_status; bool ret = false; - _init_common(kms, log, MONGOCRYPT_KMS_AWS_DECRYPT); + _init_common(kms, log, MONGOCRYPT_KMS_AWS_DECRYPT, kmsid); status = kms->status; ctx_with_status.ctx = crypto; ctx_with_status.status = mongocrypt_status_new(); @@ -170,17 +180,19 @@ bool _mongocrypt_kms_ctx_init_aws_decrypt(mongocrypt_kms_ctx_t *kms, goto done; } - if (0 == (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AWS)) { - CLIENT_ERR("aws kms not configured"); + mc_kms_creds_t kc; + if (!_mongocrypt_opts_kms_providers_lookup(kms_providers, key->kek.kmsid, &kc)) { + CLIENT_ERR("KMS provider `%s` is not configured", key->kek.kmsid); goto done; } + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_AWS); - if (!kms_providers->aws.access_key_id) { + if (!kc.value.aws.access_key_id) { CLIENT_ERR("aws access key id not provided"); goto done; } - if (!kms_providers->aws.secret_access_key) { + if (!kc.value.aws.secret_access_key) { CLIENT_ERR("aws secret access key not provided"); goto done; } @@ -201,8 +213,8 @@ bool _mongocrypt_kms_ctx_init_aws_decrypt(mongocrypt_kms_ctx_t *kms, goto done; } - if (kms_providers->aws.session_token) { - if (!kms_request_add_header_field(kms->req, "X-Amz-Security-Token", kms_providers->aws.session_token)) { + if (kc.value.aws.session_token) { + if (!kms_request_add_header_field(kms->req, "X-Amz-Security-Token", kc.value.aws.session_token)) { CLIENT_ERR("failed to set session token: %s", kms_request_get_error(kms->req)); _mongocrypt_status_append(status, ctx_with_status.status); goto done; @@ -230,12 +242,12 @@ bool _mongocrypt_kms_ctx_init_aws_decrypt(mongocrypt_kms_ctx_t *kms, goto done; } - if (!kms_request_set_access_key_id(kms->req, kms_providers->aws.access_key_id)) { + if (!kms_request_set_access_key_id(kms->req, kc.value.aws.access_key_id)) { CLIENT_ERR("failed to set aws access key id: %s", kms_request_get_error(kms->req)); _mongocrypt_status_append(status, ctx_with_status.status); goto done; } - if (!kms_request_set_secret_key(kms->req, kms_providers->aws.secret_access_key)) { + if (!kms_request_set_secret_key(kms->req, kc.value.aws.secret_access_key)) { CLIENT_ERR("failed to set aws secret access key: %s", kms_request_get_error(kms->req)); _mongocrypt_status_append(status, ctx_with_status.status); goto done; @@ -270,8 +282,9 @@ bool _mongocrypt_kms_ctx_init_aws_encrypt(mongocrypt_kms_ctx_t *kms, _mongocrypt_opts_kms_providers_t *kms_providers, _mongocrypt_ctx_opts_t *ctx_opts, _mongocrypt_buffer_t *plaintext_key_material, - _mongocrypt_log_t *log, - _mongocrypt_crypto_t *crypto) { + _mongocrypt_crypto_t *crypto, + const char *kmsid, + _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms); BSON_ASSERT_PARAM(ctx_opts); BSON_ASSERT_PARAM(kms_providers); @@ -283,7 +296,7 @@ bool _mongocrypt_kms_ctx_init_aws_encrypt(mongocrypt_kms_ctx_t *kms, ctx_with_status_t ctx_with_status; bool ret = false; - _init_common(kms, log, MONGOCRYPT_KMS_AWS_ENCRYPT); + _init_common(kms, log, MONGOCRYPT_KMS_AWS_ENCRYPT, kmsid); status = kms->status; ctx_with_status.ctx = crypto; ctx_with_status.status = mongocrypt_status_new(); @@ -303,17 +316,19 @@ bool _mongocrypt_kms_ctx_init_aws_encrypt(mongocrypt_kms_ctx_t *kms, goto done; } - if (0 == (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AWS)) { - CLIENT_ERR("aws kms not configured"); + mc_kms_creds_t kc; + if (!_mongocrypt_opts_kms_providers_lookup(kms_providers, ctx_opts->kek.kmsid, &kc)) { + CLIENT_ERR("KMS provider `%s` is not configured", ctx_opts->kek.kmsid); goto done; } + BSON_ASSERT(kc.type == MONGOCRYPT_KMS_PROVIDER_AWS); - if (!kms_providers->aws.access_key_id) { + if (!kc.value.aws.access_key_id) { CLIENT_ERR("aws access key id not provided"); goto done; } - if (!kms_providers->aws.secret_access_key) { + if (!kc.value.aws.secret_access_key) { CLIENT_ERR("aws secret access key not provided"); goto done; } @@ -337,8 +352,8 @@ bool _mongocrypt_kms_ctx_init_aws_encrypt(mongocrypt_kms_ctx_t *kms, goto done; } - if (kms_providers->aws.session_token) { - if (!kms_request_add_header_field(kms->req, "X-Amz-Security-Token", kms_providers->aws.session_token)) { + if (kc.value.aws.session_token) { + if (!kms_request_add_header_field(kms->req, "X-Amz-Security-Token", kc.value.aws.session_token)) { CLIENT_ERR("failed to set session token: %s", kms_request_get_error(kms->req)); _mongocrypt_status_append(status, ctx_with_status.status); goto done; @@ -366,12 +381,12 @@ bool _mongocrypt_kms_ctx_init_aws_encrypt(mongocrypt_kms_ctx_t *kms, goto done; } - if (!kms_request_set_access_key_id(kms->req, kms_providers->aws.access_key_id)) { + if (!kms_request_set_access_key_id(kms->req, kc.value.aws.access_key_id)) { CLIENT_ERR("failed to set aws access key id: %s", kms_request_get_error(kms->req)); _mongocrypt_status_append(status, ctx_with_status.status); goto done; } - if (!kms_request_set_secret_key(kms->req, kms_providers->aws.secret_access_key)) { + if (!kms_request_set_secret_key(kms->req, kc.value.aws.secret_access_key)) { CLIENT_ERR("failed to set aws secret access key: %s", kms_request_get_error(kms->req)); _mongocrypt_status_append(status, ctx_with_status.status); goto done; @@ -464,6 +479,10 @@ static bool _ctx_done_aws(mongocrypt_kms_ctx_t *kms, const char *json_field) { /* Parse out the {en|de}crypted result. */ http_status = kms_response_parser_status(kms->parser); response = kms_response_parser_get_response(kms->parser); + if (!response) { + CLIENT_ERR("Failed to get response from parser: %s", kms_response_parser_error(kms->parser)); + goto fail; + } body = kms_response_get_body(response, &body_len); if (http_status != 200) { @@ -541,6 +560,10 @@ static bool _ctx_done_oauth(mongocrypt_kms_ctx_t *kms) { /* Parse out the oauth token result (or error). */ http_status = kms_response_parser_status(kms->parser); response = kms_response_parser_get_response(kms->parser); + if (!response) { + CLIENT_ERR("Failed to get response from parser: %s", kms_response_parser_error(kms->parser)); + goto fail; + } body = kms_response_get_body(response, &body_len); if (body_len == 0) { @@ -614,6 +637,10 @@ static bool _ctx_done_azure_wrapkey_unwrapkey(mongocrypt_kms_ctx_t *kms) { /* Parse out the oauth token result (or error). */ http_status = kms_response_parser_status(kms->parser); response = kms_response_parser_get_response(kms->parser); + if (!response) { + CLIENT_ERR("Failed to get response from parser: %s", kms_response_parser_error(kms->parser)); + goto fail; + } body = kms_response_get_body(response, &body_len); if (body_len == 0) { @@ -704,6 +731,10 @@ static bool _ctx_done_gcp(mongocrypt_kms_ctx_t *kms, const char *json_field) { /* Parse out the {en|de}crypted result. */ http_status = kms_response_parser_status(kms->parser); response = kms_response_parser_get_response(kms->parser); + if (!response) { + CLIENT_ERR("Failed to get response from parser: %s", kms_response_parser_error(kms->parser)); + goto fail; + } body = kms_response_get_body(response, &body_len); if (http_status != 200) { @@ -826,6 +857,144 @@ static bool _ctx_done_kmip_get(mongocrypt_kms_ctx_t *kms_ctx) { return ret; } +static bool _ctx_done_kmip_create(mongocrypt_kms_ctx_t *kms_ctx) { + BSON_ASSERT_PARAM(kms_ctx); + + kms_response_t *res = NULL; + + mongocrypt_status_t *status = kms_ctx->status; + bool ret = false; + char *uid; + + res = kms_response_parser_get_response(kms_ctx->parser); + if (!res) { + CLIENT_ERR("Error getting KMIP response: %s", kms_response_parser_error(kms_ctx->parser)); + goto done; + } + + uid = kms_kmip_response_get_unique_identifier(res); + if (!uid) { + CLIENT_ERR("Error getting UniqueIdentifer from KMIP Create response: %s", kms_response_get_error(res)); + goto done; + } + + if (!_mongocrypt_buffer_steal_from_string(&kms_ctx->result, uid)) { + CLIENT_ERR("Error storing KMS UniqueIdentifer result"); + bson_free(uid); + goto done; + } + ret = true; + +done: + kms_response_destroy(res); + return ret; +} + +static bool _ctx_done_kmip_encrypt(mongocrypt_kms_ctx_t *kms_ctx) { + BSON_ASSERT_PARAM(kms_ctx); + + kms_response_t *res = NULL; + + mongocrypt_status_t *status = kms_ctx->status; + bool ret = false; + uint8_t *ciphertext; + size_t ciphertext_len; + uint8_t *iv; + size_t iv_len; + _mongocrypt_buffer_t data_buf, iv_buf; + _mongocrypt_buffer_init(&data_buf); + _mongocrypt_buffer_init(&iv_buf); + + res = kms_response_parser_get_response(kms_ctx->parser); + if (!res) { + CLIENT_ERR("Error getting KMIP response: %s", kms_response_parser_error(kms_ctx->parser)); + goto done; + } + + ciphertext = kms_kmip_response_get_data(res, &ciphertext_len); + if (!ciphertext) { + CLIENT_ERR("Error getting data from KMIP Encrypt response: %s", kms_response_get_error(res)); + goto done; + } + + iv = kms_kmip_response_get_iv(res, &iv_len); + if (!iv) { + CLIENT_ERR("Error getting IV from KMIP Encrypt response: %s", kms_response_get_error(res)); + bson_free(ciphertext); + goto done; + } + + if (iv_len != MONGOCRYPT_IV_LEN) { + CLIENT_ERR("KMIP IV response has unexpected length: %zu", iv_len); + bson_free(ciphertext); + bson_free(iv); + goto done; + } + + if (!_mongocrypt_buffer_steal_from_data_and_size(&data_buf, ciphertext, ciphertext_len)) { + CLIENT_ERR("Error storing KMS Encrypt result"); + bson_free(ciphertext); + bson_free(iv); + goto done; + } + + if (!_mongocrypt_buffer_steal_from_data_and_size(&iv_buf, iv, iv_len)) { + CLIENT_ERR("Error storing KMS Encrypt IV"); + bson_free(ciphertext); + bson_free(iv); + goto done; + } + + const _mongocrypt_buffer_t results_buf[2] = {iv_buf, data_buf}; + if (!_mongocrypt_buffer_concat(&kms_ctx->result, results_buf, 2)) { + CLIENT_ERR("Error concatenating IV and ciphertext"); + goto done; + } + + ret = true; + +done: + kms_response_destroy(res); + _mongocrypt_buffer_cleanup(&iv_buf); + _mongocrypt_buffer_cleanup(&data_buf); + return ret; +} + +static bool _ctx_done_kmip_decrypt(mongocrypt_kms_ctx_t *kms_ctx) { + BSON_ASSERT_PARAM(kms_ctx); + + kms_response_t *res = NULL; + + mongocrypt_status_t *status = kms_ctx->status; + bool ret = false; + uint8_t *ciphertext; + size_t ciphertext_len; + + res = kms_response_parser_get_response(kms_ctx->parser); + if (!res) { + CLIENT_ERR("Error getting KMIP response: %s", kms_response_parser_error(kms_ctx->parser)); + goto done; + } + + ciphertext = kms_kmip_response_get_data(res, &ciphertext_len); + if (!ciphertext) { + CLIENT_ERR("Error getting data from KMIP Decrypt response: %s", kms_response_get_error(res)); + goto done; + } + + if (!_mongocrypt_buffer_steal_from_data_and_size(&kms_ctx->result, ciphertext, ciphertext_len)) { + CLIENT_ERR("Error storing KMS Decrypt result"); + bson_free(ciphertext); + goto done; + } + + ret = true; + +done: + kms_response_destroy(res); + return ret; +} + bool mongocrypt_kms_ctx_feed(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *bytes) { if (!kms) { return false; @@ -889,6 +1058,9 @@ bool mongocrypt_kms_ctx_feed(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *byt case MONGOCRYPT_KMS_KMIP_REGISTER: return _ctx_done_kmip_register(kms); case MONGOCRYPT_KMS_KMIP_ACTIVATE: return _ctx_done_kmip_activate(kms); case MONGOCRYPT_KMS_KMIP_GET: return _ctx_done_kmip_get(kms); + case MONGOCRYPT_KMS_KMIP_ENCRYPT: return _ctx_done_kmip_encrypt(kms); + case MONGOCRYPT_KMS_KMIP_DECRYPT: return _ctx_done_kmip_decrypt(kms); + case MONGOCRYPT_KMS_KMIP_CREATE: return _ctx_done_kmip_create(kms); } } return true; @@ -948,6 +1120,7 @@ void _mongocrypt_kms_ctx_cleanup(mongocrypt_kms_ctx_t *kms) { _mongocrypt_buffer_cleanup(&kms->msg); _mongocrypt_buffer_cleanup(&kms->result); bson_free(kms->endpoint); + bson_free(kms->kmsid); } bool mongocrypt_kms_ctx_message(mongocrypt_kms_ctx_t *kms, mongocrypt_binary_t *msg) { @@ -979,24 +1152,27 @@ bool mongocrypt_kms_ctx_endpoint(mongocrypt_kms_ctx_t *kms, const char **endpoin } bool _mongocrypt_kms_ctx_init_azure_auth(mongocrypt_kms_ctx_t *kms, - _mongocrypt_log_t *log, - _mongocrypt_opts_kms_providers_t *kms_providers, - _mongocrypt_endpoint_t *key_vault_endpoint) { + const mc_kms_creds_t *kc, + _mongocrypt_endpoint_t *key_vault_endpoint, + const char *kmsid, + _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms); - BSON_ASSERT_PARAM(kms_providers); + BSON_ASSERT_PARAM(kc); kms_request_opt_t *opt = NULL; mongocrypt_status_t *status; - _mongocrypt_endpoint_t *identity_platform_endpoint; + const _mongocrypt_endpoint_t *identity_platform_endpoint; char *scope = NULL; const char *hostname; char *request_string; bool ret = false; - _init_common(kms, log, MONGOCRYPT_KMS_AZURE_OAUTH); + _init_common(kms, log, MONGOCRYPT_KMS_AZURE_OAUTH, kmsid); status = kms->status; - identity_platform_endpoint = kms_providers->azure.identity_platform_endpoint; + BSON_ASSERT(kc->type == MONGOCRYPT_KMS_PROVIDER_AZURE); + + identity_platform_endpoint = kc->value.azure.identity_platform_endpoint; if (identity_platform_endpoint) { kms->endpoint = bson_strdup(identity_platform_endpoint->host_and_port); @@ -1022,9 +1198,9 @@ bool _mongocrypt_kms_ctx_init_azure_auth(mongocrypt_kms_ctx_t *kms, kms_request_opt_set_provider(opt, KMS_REQUEST_PROVIDER_AZURE); kms->req = kms_azure_request_oauth_new(hostname, scope, - kms_providers->azure.tenant_id, - kms_providers->azure.client_id, - kms_providers->azure.client_secret, + kc->value.azure.tenant_id, + kc->value.azure.client_id, + kc->value.azure.client_secret, opt); if (kms_request_get_error(kms->req)) { CLIENT_ERR("error constructing KMS message: %s", kms_request_get_error(kms->req)); @@ -1049,11 +1225,12 @@ bool _mongocrypt_kms_ctx_init_azure_auth(mongocrypt_kms_ctx_t *kms, } bool _mongocrypt_kms_ctx_init_azure_wrapkey(mongocrypt_kms_ctx_t *kms, - _mongocrypt_log_t *log, _mongocrypt_opts_kms_providers_t *kms_providers, struct __mongocrypt_ctx_opts_t *ctx_opts, const char *access_token, - _mongocrypt_buffer_t *plaintext_key_material) { + _mongocrypt_buffer_t *plaintext_key_material, + const char *kmsid, + _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms); BSON_ASSERT_PARAM(ctx_opts); BSON_ASSERT_PARAM(plaintext_key_material); @@ -1066,7 +1243,7 @@ bool _mongocrypt_kms_ctx_init_azure_wrapkey(mongocrypt_kms_ctx_t *kms, char *request_string; bool ret = false; - _init_common(kms, log, MONGOCRYPT_KMS_AZURE_WRAPKEY); + _init_common(kms, log, MONGOCRYPT_KMS_AZURE_WRAPKEY, kmsid); status = kms->status; BSON_ASSERT(ctx_opts->kek.provider.azure.key_vault_endpoint); @@ -1114,6 +1291,7 @@ bool _mongocrypt_kms_ctx_init_azure_unwrapkey(mongocrypt_kms_ctx_t *kms, _mongocrypt_opts_kms_providers_t *kms_providers, const char *access_token, _mongocrypt_key_doc_t *key, + const char *kmsid, _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms); BSON_ASSERT_PARAM(key); @@ -1126,7 +1304,7 @@ bool _mongocrypt_kms_ctx_init_azure_unwrapkey(mongocrypt_kms_ctx_t *kms, char *request_string; bool ret = false; - _init_common(kms, log, MONGOCRYPT_KMS_AZURE_UNWRAPKEY); + _init_common(kms, log, MONGOCRYPT_KMS_AZURE_UNWRAPKEY, kmsid); status = kms->status; BSON_ASSERT(key->kek.provider.azure.key_vault_endpoint); @@ -1212,17 +1390,18 @@ static bool _sign_rsaes_pkcs1_v1_5_trampoline(void *ctx, } bool _mongocrypt_kms_ctx_init_gcp_auth(mongocrypt_kms_ctx_t *kms, - _mongocrypt_log_t *log, _mongocrypt_opts_t *crypt_opts, - _mongocrypt_opts_kms_providers_t *kms_providers, - _mongocrypt_endpoint_t *kms_endpoint) { + const mc_kms_creds_t *kc, + _mongocrypt_endpoint_t *kms_endpoint, + const char *kmsid, + _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms); - BSON_ASSERT_PARAM(kms_providers); + BSON_ASSERT_PARAM(kc); BSON_ASSERT_PARAM(crypt_opts); kms_request_opt_t *opt = NULL; mongocrypt_status_t *status; - _mongocrypt_endpoint_t *auth_endpoint; + const _mongocrypt_endpoint_t *auth_endpoint; char *scope = NULL; char *audience = NULL; const char *hostname; @@ -1230,12 +1409,14 @@ bool _mongocrypt_kms_ctx_init_gcp_auth(mongocrypt_kms_ctx_t *kms, bool ret = false; ctx_with_status_t ctx_with_status; - _init_common(kms, log, MONGOCRYPT_KMS_GCP_OAUTH); + _init_common(kms, log, MONGOCRYPT_KMS_GCP_OAUTH, kmsid); status = kms->status; ctx_with_status.ctx = crypt_opts; ctx_with_status.status = mongocrypt_status_new(); - auth_endpoint = kms_providers->gcp.endpoint; + BSON_ASSERT(kc->type == MONGOCRYPT_KMS_PROVIDER_GCP); + + auth_endpoint = kc->value.gcp.endpoint; if (auth_endpoint) { kms->endpoint = bson_strdup(auth_endpoint->host_and_port); hostname = auth_endpoint->host; @@ -1262,11 +1443,11 @@ bool _mongocrypt_kms_ctx_init_gcp_auth(mongocrypt_kms_ctx_t *kms, kms_request_opt_set_crypto_hook_sign_rsaes_pkcs1_v1_5(opt, _sign_rsaes_pkcs1_v1_5_trampoline, &ctx_with_status); } kms->req = kms_gcp_request_oauth_new(hostname, - kms_providers->gcp.email, + kc->value.gcp.email, audience, scope, - (const char *)kms_providers->gcp.private_key.data, - kms_providers->gcp.private_key.len, + (const char *)kc->value.gcp.private_key.data, + kc->value.gcp.private_key.len, opt); if (kms_request_get_error(kms->req)) { CLIENT_ERR("error constructing KMS message: %s", kms_request_get_error(kms->req)); @@ -1295,11 +1476,12 @@ bool _mongocrypt_kms_ctx_init_gcp_auth(mongocrypt_kms_ctx_t *kms, } bool _mongocrypt_kms_ctx_init_gcp_encrypt(mongocrypt_kms_ctx_t *kms, - _mongocrypt_log_t *log, _mongocrypt_opts_kms_providers_t *kms_providers, struct __mongocrypt_ctx_opts_t *ctx_opts, const char *access_token, - _mongocrypt_buffer_t *plaintext_key_material) { + _mongocrypt_buffer_t *plaintext_key_material, + const char *kmsid, + _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms); BSON_ASSERT_PARAM(ctx_opts); BSON_ASSERT_PARAM(kms_providers); @@ -1314,7 +1496,7 @@ bool _mongocrypt_kms_ctx_init_gcp_encrypt(mongocrypt_kms_ctx_t *kms, char *request_string; bool ret = false; - _init_common(kms, log, MONGOCRYPT_KMS_GCP_ENCRYPT); + _init_common(kms, log, MONGOCRYPT_KMS_GCP_ENCRYPT, kmsid); status = kms->status; if (ctx_opts->kek.provider.gcp.endpoint) { @@ -1368,6 +1550,7 @@ bool _mongocrypt_kms_ctx_init_gcp_decrypt(mongocrypt_kms_ctx_t *kms, _mongocrypt_opts_kms_providers_t *kms_providers, const char *access_token, _mongocrypt_key_doc_t *key, + const char *kmsid, _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms); BSON_ASSERT_PARAM(kms_providers); @@ -1382,7 +1565,7 @@ bool _mongocrypt_kms_ctx_init_gcp_decrypt(mongocrypt_kms_ctx_t *kms, char *request_string; bool ret = false; - _init_common(kms, log, MONGOCRYPT_KMS_GCP_DECRYPT); + _init_common(kms, log, MONGOCRYPT_KMS_GCP_DECRYPT, kmsid); status = kms->status; if (key->kek.provider.gcp.endpoint) { @@ -1435,6 +1618,7 @@ bool _mongocrypt_kms_ctx_init_kmip_register(mongocrypt_kms_ctx_t *kms_ctx, const _mongocrypt_endpoint_t *endpoint, const uint8_t *secretdata, uint32_t secretdata_len, + const char *kmsid, _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms_ctx); BSON_ASSERT_PARAM(endpoint); @@ -1445,7 +1629,7 @@ bool _mongocrypt_kms_ctx_init_kmip_register(mongocrypt_kms_ctx_t *kms_ctx, const uint8_t *reqdata; size_t reqlen; - _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_REGISTER); + _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_REGISTER, kmsid); status = kms_ctx->status; kms_ctx->endpoint = bson_strdup(endpoint->host_and_port); @@ -1471,6 +1655,7 @@ bool _mongocrypt_kms_ctx_init_kmip_register(mongocrypt_kms_ctx_t *kms_ctx, bool _mongocrypt_kms_ctx_init_kmip_activate(mongocrypt_kms_ctx_t *kms_ctx, const _mongocrypt_endpoint_t *endpoint, const char *unique_identifier, + const char *kmsid, _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms_ctx); BSON_ASSERT_PARAM(endpoint); @@ -1481,7 +1666,7 @@ bool _mongocrypt_kms_ctx_init_kmip_activate(mongocrypt_kms_ctx_t *kms_ctx, size_t reqlen; const uint8_t *reqdata; - _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_ACTIVATE); + _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_ACTIVATE, kmsid); status = kms_ctx->status; kms_ctx->endpoint = bson_strdup(endpoint->host_and_port); @@ -1507,6 +1692,7 @@ bool _mongocrypt_kms_ctx_init_kmip_activate(mongocrypt_kms_ctx_t *kms_ctx, bool _mongocrypt_kms_ctx_init_kmip_get(mongocrypt_kms_ctx_t *kms_ctx, const _mongocrypt_endpoint_t *endpoint, const char *unique_identifier, + const char *kmsid, _mongocrypt_log_t *log) { BSON_ASSERT_PARAM(kms_ctx); BSON_ASSERT_PARAM(endpoint); @@ -1517,7 +1703,7 @@ bool _mongocrypt_kms_ctx_init_kmip_get(mongocrypt_kms_ctx_t *kms_ctx, size_t reqlen; const uint8_t *reqdata; - _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_GET); + _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_GET, kmsid); status = kms_ctx->status; kms_ctx->endpoint = bson_strdup(endpoint->host_and_port); @@ -1540,6 +1726,129 @@ bool _mongocrypt_kms_ctx_init_kmip_get(mongocrypt_kms_ctx_t *kms_ctx, return ret; } +bool _mongocrypt_kms_ctx_init_kmip_create(mongocrypt_kms_ctx_t *kms_ctx, + const _mongocrypt_endpoint_t *endpoint, + const char *kmsid, + _mongocrypt_log_t *log) { + BSON_ASSERT_PARAM(kms_ctx); + BSON_ASSERT_PARAM(endpoint); + bool ret = false; + + _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_CREATE, kmsid); + mongocrypt_status_t *status = kms_ctx->status; + kms_ctx->endpoint = bson_strdup(endpoint->host_and_port); + _mongocrypt_apply_default_port(&kms_ctx->endpoint, DEFAULT_KMIP_PORT); + + kms_ctx->req = kms_kmip_request_create_new(NULL /* reserved */); + + if (kms_request_get_error(kms_ctx->req)) { + CLIENT_ERR("Error creating KMIP create request: %s", kms_request_get_error(kms_ctx->req)); + goto done; + } + + size_t reqlen; + const uint8_t *reqdata = kms_request_to_bytes(kms_ctx->req, &reqlen); + if (!_mongocrypt_buffer_copy_from_data_and_size(&kms_ctx->msg, reqdata, reqlen)) { + CLIENT_ERR("Error storing KMS request payload"); + goto done; + } + + ret = true; +done: + return ret; +} + +bool _mongocrypt_kms_ctx_init_kmip_encrypt(mongocrypt_kms_ctx_t *kms_ctx, + const _mongocrypt_endpoint_t *endpoint, + const char *unique_identifier, + const char *kmsid, + _mongocrypt_buffer_t *plaintext, + _mongocrypt_log_t *log) { + BSON_ASSERT_PARAM(kms_ctx); + BSON_ASSERT_PARAM(endpoint); + BSON_ASSERT_PARAM(plaintext); + bool ret = false; + + _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_ENCRYPT, kmsid); + mongocrypt_status_t *status = kms_ctx->status; + kms_ctx->endpoint = bson_strdup(endpoint->host_and_port); + _mongocrypt_apply_default_port(&kms_ctx->endpoint, DEFAULT_KMIP_PORT); + + kms_ctx->req = + kms_kmip_request_encrypt_new(NULL /* reserved */, unique_identifier, plaintext->data, plaintext->len); + + if (kms_request_get_error(kms_ctx->req)) { + CLIENT_ERR("Error creating KMIP encrypt request: %s", kms_request_get_error(kms_ctx->req)); + goto done; + } + + size_t reqlen; + const uint8_t *reqdata = kms_request_to_bytes(kms_ctx->req, &reqlen); + if (!_mongocrypt_buffer_copy_from_data_and_size(&kms_ctx->msg, reqdata, reqlen)) { + CLIENT_ERR("Error storing KMS request payload"); + goto done; + } + + ret = true; +done: + return ret; +} + +bool _mongocrypt_kms_ctx_init_kmip_decrypt(mongocrypt_kms_ctx_t *kms_ctx, + const _mongocrypt_endpoint_t *endpoint, + const char *kmsid, + _mongocrypt_key_doc_t *key, + _mongocrypt_log_t *log) { + BSON_ASSERT_PARAM(kms_ctx); + BSON_ASSERT_PARAM(endpoint); + BSON_ASSERT_PARAM(key); + bool ret = false; + + _init_common(kms_ctx, log, MONGOCRYPT_KMS_KMIP_DECRYPT, kmsid); + mongocrypt_status_t *status = kms_ctx->status; + kms_ctx->endpoint = bson_strdup(endpoint->host_and_port); + _mongocrypt_apply_default_port(&kms_ctx->endpoint, DEFAULT_KMIP_PORT); + + _mongocrypt_buffer_t iv; + if (!_mongocrypt_buffer_from_subrange(&iv, &key->key_material, 0, MONGOCRYPT_IV_LEN)) { + CLIENT_ERR("Error getting IV from key material"); + goto done; + } + _mongocrypt_buffer_t ciphertext; + if (!_mongocrypt_buffer_from_subrange(&ciphertext, + &key->key_material, + MONGOCRYPT_IV_LEN, + key->key_material.len - MONGOCRYPT_IV_LEN)) { + CLIENT_ERR("Error getting ciphertext from key material"); + goto done; + } + + BSON_ASSERT(key->kek.kms_provider == MONGOCRYPT_KMS_PROVIDER_KMIP); + BSON_ASSERT(key->kek.provider.kmip.delegated); + kms_ctx->req = kms_kmip_request_decrypt_new(NULL /* reserved */, + key->kek.provider.kmip.key_id, + ciphertext.data, + ciphertext.len, + iv.data, + iv.len); + + if (kms_request_get_error(kms_ctx->req)) { + CLIENT_ERR("Error creating KMIP decrypt request: %s", kms_request_get_error(kms_ctx->req)); + goto done; + } + + size_t reqlen; + const uint8_t *reqdata = kms_request_to_bytes(kms_ctx->req, &reqlen); + if (!_mongocrypt_buffer_copy_from_data_and_size(&kms_ctx->msg, reqdata, reqlen)) { + CLIENT_ERR("Error storing KMS request payload"); + goto done; + } + + ret = true; +done: + return ret; +} + static const char *set_and_ret(const char *what, uint32_t *len) { BSON_ASSERT_PARAM(what); @@ -1553,18 +1862,5 @@ const char *mongocrypt_kms_ctx_get_kms_provider(mongocrypt_kms_ctx_t *kms, uint3 BSON_ASSERT_PARAM(kms); /* len is checked in set_and_ret () before it is used */ - switch (kms->req_type) { - default: BSON_ASSERT(false && "unknown KMS request type"); - case MONGOCRYPT_KMS_AWS_ENCRYPT: - case MONGOCRYPT_KMS_AWS_DECRYPT: return set_and_ret("aws", len); - case MONGOCRYPT_KMS_AZURE_OAUTH: - case MONGOCRYPT_KMS_AZURE_WRAPKEY: - case MONGOCRYPT_KMS_AZURE_UNWRAPKEY: return set_and_ret("azure", len); - case MONGOCRYPT_KMS_GCP_OAUTH: - case MONGOCRYPT_KMS_GCP_ENCRYPT: - case MONGOCRYPT_KMS_GCP_DECRYPT: return set_and_ret("gcp", len); - case MONGOCRYPT_KMS_KMIP_REGISTER: - case MONGOCRYPT_KMS_KMIP_ACTIVATE: - case MONGOCRYPT_KMS_KMIP_GET: return set_and_ret("kmip", len); - } + return set_and_ret(kms->kmsid, len); } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h index 16dbc1d..769fea5 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h @@ -63,6 +63,7 @@ bool _mongocrypt_marking_to_ciphertext(void *ctx, mc_mincover_t *mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t sparsity, - mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT; + mongocrypt_status_t *status, + bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT; #endif /* MONGOCRYPT_MARKING_PRIVATE_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c index 443356a..a78775f 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c @@ -24,6 +24,7 @@ #include "mc-fle2-insert-update-payload-private.h" #include "mc-fle2-payload-uev-private.h" #include "mc-fle2-payload-uev-v2-private.h" +#include "mc-optional-private.h" #include "mc-range-edge-generation-private.h" #include "mc-range-encoding-private.h" #include "mc-range-mincover-private.h" @@ -33,6 +34,7 @@ #include "mongocrypt-crypto-private.h" #include "mongocrypt-key-broker-private.h" #include "mongocrypt-marking-private.h" +#include "mongocrypt-private.h" #include "mongocrypt-util-private.h" // mc_bson_type_to_string #include "mongocrypt.h" @@ -40,7 +42,7 @@ static bool _mongocrypt_marking_parse_fle1_placeholder(const bson_t *in, _mongocrypt_marking_t *out, mongocrypt_status_t *status) { - bson_iter_t iter; + bson_iter_t iter = {0}; bool has_ki = false, has_ka = false, has_a = false, has_v = false; BSON_ASSERT_PARAM(in); @@ -199,22 +201,24 @@ void _mongocrypt_marking_cleanup(_mongocrypt_marking_t *marking) { * Calculates: * E?CToken = HMAC(collectionLevel1Token, n) * E?CDerivedFromDataToken = HMAC(E?CToken, value) - * E?CDerivedFromDataTokenAndCounter = HMAC(E?CDerivedFromDataToken, c) + * E?CDerivedFromDataTokenAndContentionFactor = HMAC(E?CDerivedFromDataToken, cf) * * E?C = EDC|ESC|ECC * n = 1 for EDC, 2 for ESC, 3 for ECC - * c = maxContentionCounter + * cf = contentionFactor * - * E?CDerivedFromDataTokenAndCounter is saved to out, - * which is initialized even on failure. + * If {useContentionFactor} is False, E?CDerivedFromDataToken is saved to out, and {contentionFactor} is ignored. + * Otherwise, E?CDerivedFromDataTokenAndContentionFactor is saved to out using {contentionFactor}. + * + * Note that {out} is initialized even on failure. */ #define DERIVE_TOKEN_IMPL(Name) \ static bool _fle2_derive_##Name##_token(_mongocrypt_crypto_t *crypto, \ _mongocrypt_buffer_t *out, \ const mc_CollectionsLevel1Token_t *level1Token, \ const _mongocrypt_buffer_t *value, \ - bool useCounter, \ - int64_t counter, \ + bool useContentionFactor, \ + int64_t contentionFactor, \ mongocrypt_status_t *status) { \ BSON_ASSERT_PARAM(crypto); \ BSON_ASSERT_PARAM(out); \ @@ -235,24 +239,29 @@ void _mongocrypt_marking_cleanup(_mongocrypt_marking_t *marking) { return false; \ } \ \ - if (!useCounter) { \ + if (!useContentionFactor) { \ /* FindEqualityPayload uses *fromDataToken */ \ _mongocrypt_buffer_copy_to(mc_##Name##DerivedFromDataToken_get(fromDataToken), out); \ mc_##Name##DerivedFromDataToken_destroy(fromDataToken); \ return true; \ } \ \ - BSON_ASSERT(counter >= 0); \ - /* InsertUpdatePayload continues through *fromDataTokenAndCounter */ \ - mc_##Name##DerivedFromDataTokenAndCounter_t *fromTokenAndCounter = \ - mc_##Name##DerivedFromDataTokenAndCounter_new(crypto, fromDataToken, (uint64_t)counter, status); \ + BSON_ASSERT(contentionFactor >= 0); \ + /* InsertUpdatePayload continues through *fromDataTokenAndContentionFactor */ \ + mc_##Name##DerivedFromDataTokenAndContentionFactor_t *fromTokenAndContentionFactor = \ + mc_##Name##DerivedFromDataTokenAndContentionFactor_new(crypto, \ + fromDataToken, \ + (uint64_t)contentionFactor, \ + status); \ mc_##Name##DerivedFromDataToken_destroy(fromDataToken); \ - if (!fromTokenAndCounter) { \ + if (!fromTokenAndContentionFactor) { \ return false; \ } \ \ - _mongocrypt_buffer_copy_to(mc_##Name##DerivedFromDataTokenAndCounter_get(fromTokenAndCounter), out); \ - mc_##Name##DerivedFromDataTokenAndCounter_destroy(fromTokenAndCounter); \ + _mongocrypt_buffer_copy_to( \ + mc_##Name##DerivedFromDataTokenAndContentionFactor_get(fromTokenAndContentionFactor), \ + out); \ + mc_##Name##DerivedFromDataTokenAndContentionFactor_destroy(fromTokenAndContentionFactor); \ \ return true; \ } @@ -366,32 +375,61 @@ static bool _fle2_placeholder_aes_aead_encrypt(_mongocrypt_key_broker_t *kb, return true; } -// p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndCounter || -// ECCDerivedFromDataTokenAndCounter) +// FLE V1: p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndContentionFactor || +// ECCDerivedFromDataTokenAndContentionFactor) +// FLE V2: p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndContentionFactor) +// Range V2: p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndContentionFactor || isLeaf) static bool _fle2_derive_encrypted_token(_mongocrypt_crypto_t *crypto, _mongocrypt_buffer_t *out, + bool use_range_v2, const mc_CollectionsLevel1Token_t *collectionsLevel1Token, const _mongocrypt_buffer_t *escDerivedToken, const _mongocrypt_buffer_t *eccDerivedToken, + mc_optional_bool_t is_leaf, mongocrypt_status_t *status) { mc_ECOCToken_t *ecocToken = mc_ECOCToken_new(crypto, collectionsLevel1Token, status); if (!ecocToken) { return false; } + bool ok = false; _mongocrypt_buffer_t tmp; _mongocrypt_buffer_init(&tmp); const _mongocrypt_buffer_t *p = &tmp; if (!eccDerivedToken) { // FLE2v2 - p = escDerivedToken; + if (use_range_v2 && is_leaf.set) { + // Range V2; concat isLeaf + _mongocrypt_buffer_t isLeafBuf; + if (!_mongocrypt_buffer_copy_from_data_and_size(&isLeafBuf, (uint8_t[]){is_leaf.value}, 1)) { + CLIENT_ERR("failed to create is_leaf buffer"); + goto fail; + } + if (!_mongocrypt_buffer_concat(&tmp, (_mongocrypt_buffer_t[]){*escDerivedToken, isLeafBuf}, 2)) { + CLIENT_ERR("failed to allocate buffer"); + _mongocrypt_buffer_cleanup(&isLeafBuf); + goto fail; + } + _mongocrypt_buffer_cleanup(&isLeafBuf); + } else { + p = escDerivedToken; + } + } else { // FLE2v1 const _mongocrypt_buffer_t tokens[] = {*escDerivedToken, *eccDerivedToken}; - _mongocrypt_buffer_concat(&tmp, tokens, 2); + if (!_mongocrypt_buffer_concat(&tmp, tokens, 2)) { + CLIENT_ERR("failed to allocate buffer"); + goto fail; + } + } + + if (!_fle2_placeholder_aes_ctr_encrypt(crypto, mc_ECOCToken_get(ecocToken), p, out, status)) { + goto fail; } - const bool ok = _fle2_placeholder_aes_ctr_encrypt(crypto, mc_ECOCToken_get(ecocToken), p, out, status); + ok = true; +fail: _mongocrypt_buffer_cleanup(&tmp); mc_ECOCToken_destroy(ecocToken); return ok; @@ -466,8 +504,8 @@ static bool _mongocrypt_fle2_placeholder_common(_mongocrypt_key_broker_t *kb, _FLE2EncryptedPayloadCommon_t *ret, const _mongocrypt_buffer_t *indexKeyId, const _mongocrypt_buffer_t *value, - bool useCounter, - int64_t maxContentionCounter, + bool useContentionFactor, + int64_t contentionFactor, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(kb); BSON_ASSERT_PARAM(ret); @@ -498,8 +536,8 @@ static bool _mongocrypt_fle2_placeholder_common(_mongocrypt_key_broker_t *kb, &ret->edcDerivedToken, ret->collectionsLevel1Token, value, - useCounter, - maxContentionCounter, + useContentionFactor, + contentionFactor, status)) { goto fail; } @@ -508,8 +546,8 @@ static bool _mongocrypt_fle2_placeholder_common(_mongocrypt_key_broker_t *kb, &ret->escDerivedToken, ret->collectionsLevel1Token, value, - useCounter, - maxContentionCounter, + useContentionFactor, + contentionFactor, status)) { goto fail; } @@ -535,8 +573,8 @@ static bool _mongocrypt_fle2_placeholder_common(_mongocrypt_key_broker_t *kb, &ret->eccDerivedToken, ret->collectionsLevel1Token, value, - useCounter, - maxContentionCounter, + useContentionFactor, + contentionFactor, status)) { goto fail; } @@ -566,6 +604,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_common_v1(_mongocrypt_ BSON_ASSERT_PARAM(value_iter); BSON_ASSERT(kb->crypt); BSON_ASSERT(kb->crypt->opts.use_fle2_v2 == false); + BSON_ASSERT(kb->crypt->opts.use_range_v2 == false); BSON_ASSERT(placeholder->type == MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT); _mongocrypt_crypto_t *crypto = kb->crypt->crypto; @@ -573,10 +612,10 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_common_v1(_mongocrypt_ bool res = false; *contentionFactor = 0; - if (placeholder->maxContentionCounter > 0) { + if (placeholder->maxContentionFactor > 0) { /* Choose a random contentionFactor in the inclusive range [0, - * placeholder->maxContentionCounter] */ - if (!_mongocrypt_random_int64(crypto, placeholder->maxContentionCounter + 1, contentionFactor, status)) { + * placeholder->maxContentionFactor] */ + if (!_mongocrypt_random_int64(crypto, placeholder->maxContentionFactor + 1, contentionFactor, status)) { goto fail; } } @@ -586,7 +625,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_common_v1(_mongocrypt_ common, &placeholder->index_key_id, &value, - true, /* derive tokens using counter */ + true, /* derive tokens using contentionFactor */ *contentionFactor, status)) { goto fail; @@ -599,13 +638,15 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_common_v1(_mongocrypt_ // c := ECCDerivedToken _mongocrypt_buffer_steal(&out->eccDerivedToken, &common->eccDerivedToken); - // p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndCounter || - // ECCDerivedFromDataTokenAndCounter) + // p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndContentionFactor || + // ECCDerivedFromDataTokenAndContentionFactor) if (!_fle2_derive_encrypted_token(crypto, &out->encryptedTokens, + false, // Can't use range V2 with FLE V1 common->collectionsLevel1Token, &out->escDerivedToken, &out->eccDerivedToken, + (mc_optional_bool_t){0}, // Unset is_leaf as it's not used in V1 status)) { goto fail; } @@ -719,10 +760,10 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_common(_mongocrypt_key bool res = false; out->contentionFactor = 0; // k - if (placeholder->maxContentionCounter > 0) { + if (placeholder->maxContentionFactor > 0) { /* Choose a random contentionFactor in the inclusive range [0, - * placeholder->maxContentionCounter] */ - if (!_mongocrypt_random_int64(crypto, placeholder->maxContentionCounter + 1, &out->contentionFactor, status)) { + * placeholder->maxContentionFactor] */ + if (!_mongocrypt_random_int64(crypto, placeholder->maxContentionFactor + 1, &out->contentionFactor, status)) { goto fail; } } @@ -732,7 +773,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_common(_mongocrypt_key common, &placeholder->index_key_id, &value, - true, /* derive tokens using counter */ + true, /* derive tokens using contentionFactor */ out->contentionFactor, status)) { goto fail; @@ -744,13 +785,18 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_common(_mongocrypt_key _mongocrypt_buffer_steal(&out->escDerivedToken, &common->escDerivedToken); BSON_ASSERT(common->eccDerivedToken.data == NULL); - // p := EncryptCBC(ECOCToken, ESCDerivedFromDataTokenAndCounter) - if (!_fle2_derive_encrypted_token(crypto, - &out->encryptedTokens, - common->collectionsLevel1Token, - &out->escDerivedToken, - NULL, // unused in v2 - status)) { + // p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndContentionFactor) + // Or in Range V2, when using range: p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndContentionFactor || 0x00) + if (!_fle2_derive_encrypted_token( + crypto, + &out->encryptedTokens, + kb->crypt->opts.use_range_v2, + common->collectionsLevel1Token, + &out->escDerivedToken, + NULL, // unused in v2 + // If this is a range insert, we append isLeaf to the encryptedTokens. Otherwise, we don't. + placeholder->algorithm == MONGOCRYPT_FLE2_ALGORITHM_RANGE ? OPT_BOOL(false) : (mc_optional_bool_t){0}, + status)) { goto fail; } @@ -850,7 +896,8 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertext(_mongocrypt // get_edges creates and returns edges from an FLE2RangeInsertSpec. Returns NULL // on error. -static mc_edges_t *get_edges(mc_FLE2RangeInsertSpec_t *insertSpec, size_t sparsity, mongocrypt_status_t *status) { +static mc_edges_t * +get_edges(mc_FLE2RangeInsertSpec_t *insertSpec, size_t sparsity, mongocrypt_status_t *status, bool use_range_v2) { BSON_ASSERT_PARAM(insertSpec); bson_type_t value_type = bson_iter_type(&insertSpec->v); @@ -859,28 +906,36 @@ static mc_edges_t *get_edges(mc_FLE2RangeInsertSpec_t *insertSpec, size_t sparsi return mc_getEdgesInt32((mc_getEdgesInt32_args_t){.value = bson_iter_int32(&insertSpec->v), .min = OPT_I32(bson_iter_int32(&insertSpec->min)), .max = OPT_I32(bson_iter_int32(&insertSpec->max)), - .sparsity = sparsity}, - status); + .sparsity = sparsity, + .trimFactor = insertSpec->trimFactor}, + status, + use_range_v2); } else if (value_type == BSON_TYPE_INT64) { return mc_getEdgesInt64((mc_getEdgesInt64_args_t){.value = bson_iter_int64(&insertSpec->v), .min = OPT_I64(bson_iter_int64(&insertSpec->min)), .max = OPT_I64(bson_iter_int64(&insertSpec->max)), - .sparsity = sparsity}, - status); + .sparsity = sparsity, + .trimFactor = insertSpec->trimFactor}, + status, + use_range_v2); } else if (value_type == BSON_TYPE_DATE_TIME) { return mc_getEdgesInt64((mc_getEdgesInt64_args_t){.value = bson_iter_date_time(&insertSpec->v), .min = OPT_I64(bson_iter_date_time(&insertSpec->min)), .max = OPT_I64(bson_iter_date_time(&insertSpec->max)), - .sparsity = sparsity}, - status); + .sparsity = sparsity, + .trimFactor = insertSpec->trimFactor}, + status, + use_range_v2); } else if (value_type == BSON_TYPE_DOUBLE) { - mc_getEdgesDouble_args_t args = {.value = bson_iter_double(&insertSpec->v), .sparsity = sparsity}; + mc_getEdgesDouble_args_t args = {.value = bson_iter_double(&insertSpec->v), + .sparsity = sparsity, + .trimFactor = insertSpec->trimFactor}; if (insertSpec->precision.set) { // If precision is set, pass min/max/precision to mc_getEdgesDouble. // Do not pass min/max if precision is not set. All three must be set @@ -890,7 +945,7 @@ static mc_edges_t *get_edges(mc_FLE2RangeInsertSpec_t *insertSpec, size_t sparsi args.precision = insertSpec->precision; } - return mc_getEdgesDouble(args, status); + return mc_getEdgesDouble(args, status, use_range_v2); } else if (value_type == BSON_TYPE_DECIMAL128) { @@ -899,6 +954,7 @@ static mc_edges_t *get_edges(mc_FLE2RangeInsertSpec_t *insertSpec, size_t sparsi mc_getEdgesDecimal128_args_t args = { .value = value, .sparsity = sparsity, + .trimFactor = insertSpec->trimFactor, }; if (insertSpec->precision.set) { const mc_dec128 min = mc_dec128_from_bson_iter(&insertSpec->min); @@ -907,7 +963,7 @@ static mc_edges_t *get_edges(mc_FLE2RangeInsertSpec_t *insertSpec, size_t sparsi args.max = OPT_MC_DEC128(max); args.precision = insertSpec->precision; } - return mc_getEdgesDecimal128(args, status); + return mc_getEdgesDecimal128(args, status, use_range_v2); #else // ↑↑↑↑↑↑↑↑ With Decimal128 / Without ↓↓↓↓↓↓↓↓↓↓ CLIENT_ERR("unsupported BSON type (Decimal128) for range: libmongocrypt " "was built without extended Decimal128 support"); @@ -939,6 +995,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange_v1( BSON_ASSERT_PARAM(status); BSON_ASSERT(kb->crypt); BSON_ASSERT(kb->crypt->opts.use_fle2_v2 == false); + BSON_ASSERT(kb->crypt->opts.use_range_v2 == false); BSON_ASSERT(marking->type == MONGOCRYPT_MARKING_FLE2_ENCRYPTION); BSON_ASSERT(marking->fle2.algorithm == MONGOCRYPT_FLE2_ALGORITHM_RANGE); @@ -952,7 +1009,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange_v1( // Parse the value ("v"), min ("min"), and max ("max") from // FLE2EncryptionPlaceholder for range insert. mc_FLE2RangeInsertSpec_t insertSpec; - if (!mc_FLE2RangeInsertSpec_parse(&insertSpec, &placeholder->v_iter, status)) { + if (!mc_FLE2RangeInsertSpec_parse(&insertSpec, &placeholder->v_iter, kb->crypt->opts.use_range_v2, status)) { goto fail; } @@ -970,7 +1027,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange_v1( // g:= array { BSON_ASSERT(placeholder->sparsity >= 0 && (uint64_t)placeholder->sparsity <= (uint64_t)SIZE_MAX); - edges = get_edges(&insertSpec, (size_t)placeholder->sparsity, status); + edges = get_edges(&insertSpec, (size_t)placeholder->sparsity, status, kb->crypt->opts.use_range_v2); if (!edges) { goto fail; } @@ -993,7 +1050,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange_v1( &edge_tokens, &placeholder->index_key_id, &edge_buf, - true, /* derive tokens using counter */ + true, /* derive tokens using contentionFactor */ contentionFactor, status)) { goto fail_loop; @@ -1006,13 +1063,15 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange_v1( // c := ECCDerivedToken _mongocrypt_buffer_steal(&etc.eccDerivedToken, &edge_tokens.eccDerivedToken); - // p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndCounter || - // ECCDerivedFromDataTokenAndCounter) + // p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndContentionFactor || + // ECCDerivedFromDataTokenAndContentionFactor) if (!_fle2_derive_encrypted_token(kb->crypt->crypto, &etc.encryptedTokens, + false, // Range V2 is incompatible with FLE V1 edge_tokens.collectionsLevel1Token, &etc.escDerivedToken, &etc.eccDerivedToken, + (mc_optional_bool_t){0}, // Dummy value for isLeaf, unused in FLE V1 status)) { goto fail_loop; } @@ -1071,6 +1130,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo BSON_ASSERT_PARAM(ciphertext); BSON_ASSERT(kb->crypt); BSON_ASSERT(marking->type == MONGOCRYPT_MARKING_FLE2_ENCRYPTION); + const bool use_range_v2 = kb->crypt->opts.use_range_v2; if (!kb->crypt->opts.use_fle2_v2) { return _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange_v1(kb, marking, ciphertext, status); @@ -1086,7 +1146,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo // Parse the value ("v"), min ("min"), and max ("max") from // FLE2EncryptionPlaceholder for range insert. mc_FLE2RangeInsertSpec_t insertSpec; - if (!mc_FLE2RangeInsertSpec_parse(&insertSpec, &placeholder->v_iter, status)) { + if (!mc_FLE2RangeInsertSpec_parse(&insertSpec, &placeholder->v_iter, use_range_v2, status)) { goto fail; } @@ -1102,7 +1162,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo // g:= array { BSON_ASSERT(placeholder->sparsity >= 0 && (uint64_t)placeholder->sparsity <= (uint64_t)SIZE_MAX); - edges = get_edges(&insertSpec, (size_t)placeholder->sparsity, status); + edges = get_edges(&insertSpec, (size_t)placeholder->sparsity, status, kb->crypt->opts.use_range_v2); if (!edges) { goto fail; } @@ -1111,6 +1171,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo // Create an EdgeTokenSet from each edge. bool loop_ok = false; const char *edge = mc_edges_get(edges, i); + bool is_leaf = mc_edges_is_leaf(edges, edge); _mongocrypt_buffer_t edge_buf = {0}; _FLE2EncryptedPayloadCommon_t edge_tokens = {{0}}; _mongocrypt_buffer_t encryptedTokens = {0}; @@ -1125,7 +1186,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo &edge_tokens, &placeholder->index_key_id, &edge_buf, - true, /* derive tokens using counter */ + true, /* derive tokens using contentionFactor */ payload.contentionFactor, status)) { goto fail_loop; @@ -1140,12 +1201,15 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo // l := serverDerivedFromDataToken _mongocrypt_buffer_steal(&etc.serverDerivedFromDataToken, &edge_tokens.serverDerivedFromDataToken); - // p := EncryptCBC(ECOCToken, ESCDerivedFromDataTokenAndCounter) + // p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndContentionFactor) + // Or in Range V2: p := EncryptCTR(ECOCToken, ESCDerivedFromDataTokenAndContentionFactor || isLeaf) if (!_fle2_derive_encrypted_token(kb->crypt->crypto, &etc.encryptedTokens, + kb->crypt->opts.use_range_v2, edge_tokens.collectionsLevel1Token, &etc.escDerivedToken, NULL, // ecc unsed in FLE2v2 + OPT_BOOL(is_leaf), status)) { goto fail_loop; } @@ -1163,10 +1227,17 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo } } + // Include "range" payload fields introduced in SERVER-91889. + payload.sparsity = OPT_I64(placeholder->sparsity); + payload.precision = insertSpec.precision; + payload.trimFactor = OPT_I32(mc_edges_get_used_trimFactor(edges)); + bson_value_copy(bson_iter_value(&insertSpec.min), &payload.indexMin); + bson_value_copy(bson_iter_value(&insertSpec.max), &payload.indexMax); + { bson_t out; bson_init(&out); - mc_FLE2InsertUpdatePayloadV2_serializeForRange(&payload, &out); + mc_FLE2InsertUpdatePayloadV2_serializeForRange(&payload, &out, use_range_v2); _mongocrypt_buffer_steal_from_bson(&ciphertext->data, &out); } // Do not set ciphertext->original_bson_type and ciphertext->key_id. They are @@ -1185,7 +1256,7 @@ static bool _mongocrypt_fle2_placeholder_to_insert_update_ciphertextForRange(_mo /** * Payload subtype 5: FLE2FindEqualityPayload * - * {d: EDC, s: ESC, c: ECC, e: serverToken, cm: contentionCounter} + * {d: EDC, s: ESC, c: ECC, e: serverToken, cm: maxContentionFactor} */ static bool _mongocrypt_fle2_placeholder_to_find_ciphertext_v1(_mongocrypt_key_broker_t *kb, _mongocrypt_marking_t *marking, @@ -1213,8 +1284,8 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertext_v1(_mongocrypt_key_b &common, &placeholder->index_key_id, &value, - false, /* derive tokens without counter */ - placeholder->maxContentionCounter, + false, /* derive tokens without contentionFactor */ + placeholder->maxContentionFactor, /* ignored */ status)) { goto fail; } @@ -1230,7 +1301,7 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertext_v1(_mongocrypt_key_b _mongocrypt_buffer_copy_to(mc_ServerDataEncryptionLevel1Token_get(common.serverDataEncryptionLevel1Token), &payload.serverEncryptionToken); - payload.maxContentionCounter = placeholder->maxContentionCounter; + payload.maxContentionFactor = placeholder->maxContentionFactor; { bson_t out; @@ -1255,7 +1326,7 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertext_v1(_mongocrypt_key_b * Payload subtype 12: FLE2FindEqualityPayloadV2 * Delegates to ..._find_ciphertext_v1 when crypt->opts.use_fle2_v2 == false. * - * {d: EDC, s: ESC, l: serverDerivedFromDataToken, cm: contentionCounter} + * {d: EDC, s: ESC, l: serverDerivedFromDataToken, cm: maxContentionFactor} */ static bool _mongocrypt_fle2_placeholder_to_find_ciphertext(_mongocrypt_key_broker_t *kb, _mongocrypt_marking_t *marking, @@ -1287,8 +1358,8 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertext(_mongocrypt_key_brok &common, &placeholder->index_key_id, &value, - false, /* derive tokens without counter */ - placeholder->maxContentionCounter, + false, /* derive tokens without contentionFactor */ + placeholder->maxContentionFactor, /* ignored */ status)) { goto fail; } @@ -1301,8 +1372,8 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertext(_mongocrypt_key_brok // l := serverDerivedFromDataToken _mongocrypt_buffer_steal(&payload.serverDerivedFromDataToken, &common.serverDerivedFromDataToken); - // cm := maxContentionCounter - payload.maxContentionCounter = placeholder->maxContentionCounter; + // cm := maxContentionFactor + payload.maxContentionFactor = placeholder->maxContentionFactor; { bson_t out; @@ -1329,8 +1400,10 @@ static bool isInfinite(bson_iter_t *iter) { // mc_get_mincover_from_FLE2RangeFindSpec creates and returns a mincover from an // FLE2RangeFindSpec. Returns NULL on error. -mc_mincover_t * -mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t sparsity, mongocrypt_status_t *status) { +mc_mincover_t *mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, + size_t sparsity, + mongocrypt_status_t *status, + bool use_range_v2) { BSON_ASSERT_PARAM(findSpec); BSON_ASSERT(findSpec->edgesInfo.set); @@ -1381,6 +1454,7 @@ mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t BSON_ASSERT(bson_iter_type(&upperBound) == BSON_TYPE_INT32); BSON_ASSERT(bson_iter_type(&findSpec->edgesInfo.value.indexMin) == BSON_TYPE_INT32); BSON_ASSERT(bson_iter_type(&findSpec->edgesInfo.value.indexMax) == BSON_TYPE_INT32); + return mc_getMincoverInt32( (mc_getMincoverInt32_args_t){.lowerBound = bson_iter_int32(&lowerBound), .includeLowerBound = includeLowerBound, @@ -1388,8 +1462,10 @@ mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t .includeUpperBound = includeUpperBound, .min = OPT_I32(bson_iter_int32(&findSpec->edgesInfo.value.indexMin)), .max = OPT_I32(bson_iter_int32(&findSpec->edgesInfo.value.indexMax)), - .sparsity = sparsity}, - status); + .sparsity = sparsity, + .trimFactor = findSpec->edgesInfo.value.trimFactor}, + status, + use_range_v2); case BSON_TYPE_INT64: BSON_ASSERT(bson_iter_type(&lowerBound) == BSON_TYPE_INT64); @@ -1403,8 +1479,10 @@ mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t .includeUpperBound = includeUpperBound, .min = OPT_I64(bson_iter_int64(&findSpec->edgesInfo.value.indexMin)), .max = OPT_I64(bson_iter_int64(&findSpec->edgesInfo.value.indexMax)), - .sparsity = sparsity}, - status); + .sparsity = sparsity, + .trimFactor = findSpec->edgesInfo.value.trimFactor}, + status, + use_range_v2); case BSON_TYPE_DATE_TIME: BSON_ASSERT(bson_iter_type(&lowerBound) == BSON_TYPE_DATE_TIME); BSON_ASSERT(bson_iter_type(&upperBound) == BSON_TYPE_DATE_TIME); @@ -1417,8 +1495,10 @@ mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t .includeUpperBound = includeUpperBound, .min = OPT_I64(bson_iter_date_time(&findSpec->edgesInfo.value.indexMin)), .max = OPT_I64(bson_iter_date_time(&findSpec->edgesInfo.value.indexMax)), - .sparsity = sparsity}, - status); + .sparsity = sparsity, + .trimFactor = findSpec->edgesInfo.value.trimFactor}, + status, + use_range_v2); case BSON_TYPE_DOUBLE: { BSON_ASSERT(bson_iter_type(&lowerBound) == BSON_TYPE_DOUBLE); BSON_ASSERT(bson_iter_type(&upperBound) == BSON_TYPE_DOUBLE); @@ -1429,7 +1509,8 @@ mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t .includeLowerBound = includeLowerBound, .upperBound = bson_iter_double(&upperBound), .includeUpperBound = includeUpperBound, - .sparsity = sparsity}; + .sparsity = sparsity, + .trimFactor = findSpec->edgesInfo.value.trimFactor}; if (findSpec->edgesInfo.value.precision.set) { // If precision is set, pass min/max/precision to mc_getMincoverDouble. // Do not pass min/max if precision is not set. All three must be set @@ -1438,7 +1519,7 @@ mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t args.max = OPT_DOUBLE(bson_iter_double(&findSpec->edgesInfo.value.indexMax)); args.precision = findSpec->edgesInfo.value.precision; } - return mc_getMincoverDouble(args, status); + return mc_getMincoverDouble(args, status, use_range_v2); } case BSON_TYPE_DECIMAL128: { #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT @@ -1447,19 +1528,18 @@ mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t BSON_ASSERT(bson_iter_type(&findSpec->edgesInfo.value.indexMin) == BSON_TYPE_DECIMAL128); BSON_ASSERT(bson_iter_type(&findSpec->edgesInfo.value.indexMax) == BSON_TYPE_DECIMAL128); - mc_getMincoverDecimal128_args_t args = { - .lowerBound = mc_dec128_from_bson_iter(&lowerBound), - .includeLowerBound = includeLowerBound, - .upperBound = mc_dec128_from_bson_iter(&upperBound), - .includeUpperBound = includeUpperBound, - .sparsity = sparsity, - }; + mc_getMincoverDecimal128_args_t args = {.lowerBound = mc_dec128_from_bson_iter(&lowerBound), + .includeLowerBound = includeLowerBound, + .upperBound = mc_dec128_from_bson_iter(&upperBound), + .includeUpperBound = includeUpperBound, + .sparsity = sparsity, + .trimFactor = findSpec->edgesInfo.value.trimFactor}; if (findSpec->edgesInfo.value.precision.set) { args.min = OPT_MC_DEC128(mc_dec128_from_bson_iter(&findSpec->edgesInfo.value.indexMin)); args.max = OPT_MC_DEC128(mc_dec128_from_bson_iter(&findSpec->edgesInfo.value.indexMax)); args.precision = findSpec->edgesInfo.value.precision; } - return mc_getMincoverDecimal128(args, status); + return mc_getMincoverDecimal128(args, status, use_range_v2); #else // ↑↑↑↑↑↑↑↑ With Decimal128 / Without ↓↓↓↓↓↓↓↓↓↓ CLIENT_ERR("FLE2 find is not supported for Decimal128: libmongocrypt " "was built without Decimal128 support"); @@ -1491,7 +1571,7 @@ mc_get_mincover_from_FLE2RangeFindSpec(mc_FLE2RangeFindSpec_t *findSpec, size_t /** * Payload subtype 10: FLE2FindRangePayload * - * {e: serverToken, cm: contentionCounter, + * {e: serverToken, cm: maxContentionFactor, * g: [{d: EDC, s: ESC, c: ECC}, ...]} */ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange_v1(_mongocrypt_key_broker_t *kb, @@ -1503,6 +1583,7 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange_v1(_mongocry BSON_ASSERT_PARAM(ciphertext); BSON_ASSERT(kb->crypt); + const bool use_range_v2 = kb->crypt->opts.use_range_v2; _mongocrypt_crypto_t *crypto = kb->crypt->crypto; mc_FLE2EncryptionPlaceholder_t *placeholder = &marking->fle2; mc_FLE2FindRangePayload_t payload; @@ -1520,13 +1601,13 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange_v1(_mongocry // Parse the query bounds and index bounds from FLE2EncryptionPlaceholder for // range find. mc_FLE2RangeFindSpec_t findSpec; - if (!mc_FLE2RangeFindSpec_parse(&findSpec, &placeholder->v_iter, status)) { + if (!mc_FLE2RangeFindSpec_parse(&findSpec, &placeholder->v_iter, use_range_v2, status)) { goto fail; } if (findSpec.edgesInfo.set) { - // cm := Queryable Encryption max counter - payload.payload.value.maxContentionCounter = placeholder->maxContentionCounter; + // cm := Queryable Encryption max contentionFactor + payload.payload.value.maxContentionFactor = placeholder->maxContentionFactor; // e := ServerDataEncryptionLevel1Token { @@ -1547,7 +1628,8 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange_v1(_mongocry // g:= array { BSON_ASSERT(placeholder->sparsity >= 0 && (uint64_t)placeholder->sparsity <= (uint64_t)SIZE_MAX); - mincover = mc_get_mincover_from_FLE2RangeFindSpec(&findSpec, (size_t)placeholder->sparsity, status); + mincover = + mc_get_mincover_from_FLE2RangeFindSpec(&findSpec, (size_t)placeholder->sparsity, status, use_range_v2); if (!mincover) { goto fail; } @@ -1569,8 +1651,8 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange_v1(_mongocry &edge_tokens, &placeholder->index_key_id, &edge_buf, - false, /* derive tokens using counter */ - placeholder->maxContentionCounter, + false, /* derive tokens using contentionFactor */ + placeholder->maxContentionFactor, /* ignored */ status)) { goto fail_loop; } @@ -1626,7 +1708,7 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange_v1(_mongocry * Delegates to ..._find_ciphertextForRange_v1 * when crypt->opts.use_fle2_v2 is false * - * {cm: contentionCounter, + * {cm: maxContentionFactor, * g: [{d: EDC, s: ESC, l: serverDerivedFromDataToken}, ...]} */ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange(_mongocrypt_key_broker_t *kb, @@ -1641,6 +1723,7 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange(_mongocrypt_ return _mongocrypt_fle2_placeholder_to_find_ciphertextForRange_v1(kb, marking, ciphertext, status); } + const bool use_range_v2 = kb->crypt->opts.use_range_v2; mc_FLE2EncryptionPlaceholder_t *placeholder = &marking->fle2; mc_FLE2FindRangePayloadV2_t payload; bool res = false; @@ -1656,18 +1739,19 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange(_mongocrypt_ // Parse the query bounds and index bounds from FLE2EncryptionPlaceholder for // range find. mc_FLE2RangeFindSpec_t findSpec; - if (!mc_FLE2RangeFindSpec_parse(&findSpec, &placeholder->v_iter, status)) { + if (!mc_FLE2RangeFindSpec_parse(&findSpec, &placeholder->v_iter, use_range_v2, status)) { goto fail; } if (findSpec.edgesInfo.set) { - // cm := Queryable Encryption max counter - payload.payload.value.maxContentionCounter = placeholder->maxContentionCounter; + // cm := Queryable Encryption max contentionFactor + payload.payload.value.maxContentionFactor = placeholder->maxContentionFactor; // g:= array { BSON_ASSERT(placeholder->sparsity >= 0 && (uint64_t)placeholder->sparsity <= (uint64_t)SIZE_MAX); - mincover = mc_get_mincover_from_FLE2RangeFindSpec(&findSpec, (size_t)placeholder->sparsity, status); + mincover = + mc_get_mincover_from_FLE2RangeFindSpec(&findSpec, (size_t)placeholder->sparsity, status, use_range_v2); if (!mincover) { goto fail; } @@ -1689,8 +1773,8 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange(_mongocrypt_ &edge_tokens, &placeholder->index_key_id, &edge_buf, - false, /* derive tokens using counter */ - placeholder->maxContentionCounter, + false, /* derive tokens without using contentionFactor */ + placeholder->maxContentionFactor, /* ignored */ status)) { goto fail_loop; } @@ -1715,6 +1799,15 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange(_mongocrypt_ } } payload.payload.set = true; + + if (use_range_v2) { + // Include "range" payload fields introduced in SERVER-91889. + payload.sparsity = OPT_I64(placeholder->sparsity); + payload.precision = findSpec.edgesInfo.value.precision; + payload.trimFactor = OPT_I32(mc_mincover_get_used_trimFactor(mincover)); + bson_value_copy(bson_iter_value(&findSpec.edgesInfo.value.indexMin), &payload.indexMin); + bson_value_copy(bson_iter_value(&findSpec.edgesInfo.value.indexMax), &payload.indexMax); + } } payload.payloadId = findSpec.payloadId; @@ -1724,7 +1817,7 @@ static bool _mongocrypt_fle2_placeholder_to_find_ciphertextForRange(_mongocrypt_ // Serialize. { bson_t out = BSON_INITIALIZER; - mc_FLE2FindRangePayloadV2_serialize(&payload, &out); + mc_FLE2FindRangePayloadV2_serialize(&payload, &out, use_range_v2); _mongocrypt_buffer_steal_from_bson(&ciphertext->data, &out); } _mongocrypt_buffer_steal(&ciphertext->key_id, &placeholder->index_key_id); diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts-private.h index 92061bd..4c7b77d 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts-private.h @@ -26,6 +26,7 @@ #include "mongocrypt-kek-private.h" #include "mongocrypt-log-private.h" #include "mongocrypt.h" +#include typedef struct { char *tenant_id; @@ -56,16 +57,44 @@ typedef struct { _mongocrypt_endpoint_t *endpoint; } _mongocrypt_opts_kms_provider_kmip_t; +typedef struct { + // `type` identifies the set field in `value`. + _mongocrypt_kms_provider_t type; + + union { + _mongocrypt_opts_kms_provider_local_t local; + _mongocrypt_opts_kms_provider_aws_t aws; + _mongocrypt_opts_kms_provider_azure_t azure; + _mongocrypt_opts_kms_provider_gcp_t gcp; + _mongocrypt_opts_kms_provider_kmip_t kmip; + } value; +} mc_kms_creds_t; + typedef struct { int configured_providers; /* A bit set of _mongocrypt_kms_provider_t */ int need_credentials; /* A bit set of _mongocrypt_kms_provider_t */ - _mongocrypt_opts_kms_provider_local_t local; - _mongocrypt_opts_kms_provider_aws_t aws; - _mongocrypt_opts_kms_provider_azure_t azure; - _mongocrypt_opts_kms_provider_gcp_t gcp; - _mongocrypt_opts_kms_provider_kmip_t kmip; + // Fields suffixed with `_mut` are mutated when constructing the `_mongocrypt_opts_kms_providers_t`. + // Prefer using `_mongocrypt_opts_kms_providers_lookup` to read the values. + _mongocrypt_opts_kms_provider_local_t local_mut; + _mongocrypt_opts_kms_provider_aws_t aws_mut; + _mongocrypt_opts_kms_provider_azure_t azure_mut; + _mongocrypt_opts_kms_provider_gcp_t gcp_mut; + _mongocrypt_opts_kms_provider_kmip_t kmip_mut; + // `named_mut` stores a list of named KMS providers. + mc_array_t named_mut; } _mongocrypt_opts_kms_providers_t; +void _mongocrypt_opts_kms_providers_init(_mongocrypt_opts_kms_providers_t *kms_providers); + +bool _mongocrypt_parse_kms_providers(mongocrypt_binary_t *kms_providers_definition, + _mongocrypt_opts_kms_providers_t *kms_providers, + mongocrypt_status_t *status, + _mongocrypt_log_t *log); + +bool _mongocrypt_opts_kms_providers_lookup(const _mongocrypt_opts_kms_providers_t *kms_providers, + const char *kmsid, + mc_kms_creds_t *out); + typedef struct { mongocrypt_log_fn_t log_fn; void *log_ctx; @@ -86,11 +115,15 @@ typedef struct { mstr crypt_shared_lib_override_path; bool use_need_kms_credentials_state; + bool use_need_mongo_collinfo_with_db_state; bool bypass_query_analysis; // When creating new encrypted payloads, // use V2 variants of the FLE2 datatypes. bool use_fle2_v2; + + // Use the Queryable Encryption Range V2 protocol. + bool use_range_v2; } _mongocrypt_opts_t; void _mongocrypt_opts_kms_providers_cleanup(_mongocrypt_opts_kms_providers_t *kms_providers); @@ -120,6 +153,14 @@ bool _mongocrypt_opts_kms_providers_validate(_mongocrypt_opts_t *opts, */ bool _mongocrypt_parse_optional_utf8(const bson_t *bson, const char *dotkey, char **out, mongocrypt_status_t *status); +/* + * Parse an optional boolean value from BSON. + * @dotkey may be a dot separated key like: "a.b.c". + * @*out is set to a copy of the value if found, false otherwise. + * Returns true if no error occured. + */ +bool _mongocrypt_parse_optional_bool(const bson_t *bson, const char *dotkey, bool *out, mongocrypt_status_t *status); + /* * Parse a required UTF-8 value from BSON. * @dotkey may be a dot separated key like: "a.b.c". @@ -200,4 +241,8 @@ bool _mongocrypt_check_allowed_fields_va(const bson_t *bson, const char *dotkey, #define _mongocrypt_check_allowed_fields(bson, path, status, ...) \ _mongocrypt_check_allowed_fields_va(bson, path, status, __VA_ARGS__, NULL) +bool mc_kmsid_parse(const char *kmsid, + _mongocrypt_kms_provider_t *type_out, + const char **name_out, + mongocrypt_status_t *status); #endif /* MONGOCRYPT_OPTS_PRIVATE_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c index a028811..dc6680a 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c @@ -19,12 +19,24 @@ #include "mongocrypt-log-private.h" #include "mongocrypt-opts-private.h" #include "mongocrypt-private.h" +#include // mc_iter_document_as_bson #include +typedef struct { + mc_kms_creds_t creds; + char *kmsid; +} mc_kms_creds_with_id_t; + +void _mongocrypt_opts_kms_providers_init(_mongocrypt_opts_kms_providers_t *kms_providers) { + _mc_array_init(&kms_providers->named_mut, sizeof(mc_kms_creds_with_id_t)); +} + void _mongocrypt_opts_init(_mongocrypt_opts_t *opts) { BSON_ASSERT_PARAM(opts); memset(opts, 0, sizeof(*opts)); + opts->use_range_v2 = true; + _mongocrypt_opts_kms_providers_init(&opts->kms_providers); } static void _mongocrypt_opts_kms_provider_azure_cleanup(_mongocrypt_opts_kms_provider_azure_t *kms_provider_azure) { @@ -48,17 +60,58 @@ static void _mongocrypt_opts_kms_provider_gcp_cleanup(_mongocrypt_opts_kms_provi bson_free(kms_provider_gcp->access_token); } +static void _mongocrypt_opts_kms_provider_local_cleanup(_mongocrypt_opts_kms_provider_local_t *kms_provider_local) { + _mongocrypt_buffer_cleanup(&kms_provider_local->key); +} + +static void _mongocrypt_opts_kms_provider_aws_cleanup(_mongocrypt_opts_kms_provider_aws_t *kms_provider_aws) { + bson_free(kms_provider_aws->secret_access_key); + bson_free(kms_provider_aws->access_key_id); + bson_free(kms_provider_aws->session_token); +} + +static void _mongocrypt_opts_kms_provider_kmip_cleanup(_mongocrypt_opts_kms_provider_kmip_t *kms_provider_kmip) { + _mongocrypt_endpoint_destroy(kms_provider_kmip->endpoint); +} + void _mongocrypt_opts_kms_providers_cleanup(_mongocrypt_opts_kms_providers_t *kms_providers) { if (!kms_providers) { return; } - bson_free(kms_providers->aws.secret_access_key); - bson_free(kms_providers->aws.access_key_id); - bson_free(kms_providers->aws.session_token); - _mongocrypt_buffer_cleanup(&kms_providers->local.key); - _mongocrypt_opts_kms_provider_azure_cleanup(&kms_providers->azure); - _mongocrypt_opts_kms_provider_gcp_cleanup(&kms_providers->gcp); - _mongocrypt_endpoint_destroy(kms_providers->kmip.endpoint); + _mongocrypt_opts_kms_provider_aws_cleanup(&kms_providers->aws_mut); + _mongocrypt_opts_kms_provider_local_cleanup(&kms_providers->local_mut); + _mongocrypt_opts_kms_provider_azure_cleanup(&kms_providers->azure_mut); + _mongocrypt_opts_kms_provider_gcp_cleanup(&kms_providers->gcp_mut); + _mongocrypt_opts_kms_provider_kmip_cleanup(&kms_providers->kmip_mut); + for (size_t i = 0; i < kms_providers->named_mut.len; i++) { + mc_kms_creds_with_id_t kcwid = _mc_array_index(&kms_providers->named_mut, mc_kms_creds_with_id_t, i); + switch (kcwid.creds.type) { + default: + case MONGOCRYPT_KMS_PROVIDER_NONE: break; + case MONGOCRYPT_KMS_PROVIDER_AWS: { + _mongocrypt_opts_kms_provider_aws_cleanup(&kcwid.creds.value.aws); + break; + } + case MONGOCRYPT_KMS_PROVIDER_LOCAL: { + _mongocrypt_opts_kms_provider_local_cleanup(&kcwid.creds.value.local); + break; + } + case MONGOCRYPT_KMS_PROVIDER_AZURE: { + _mongocrypt_opts_kms_provider_azure_cleanup(&kcwid.creds.value.azure); + break; + } + case MONGOCRYPT_KMS_PROVIDER_GCP: { + _mongocrypt_opts_kms_provider_gcp_cleanup(&kcwid.creds.value.gcp); + break; + } + case MONGOCRYPT_KMS_PROVIDER_KMIP: { + _mongocrypt_endpoint_destroy(kcwid.creds.value.kmip.endpoint); + break; + } + } + bson_free(kcwid.kmsid); + } + _mc_array_destroy(&kms_providers->named_mut); } void _mongocrypt_opts_merge_kms_providers(_mongocrypt_opts_kms_providers_t *dest, @@ -67,23 +120,23 @@ void _mongocrypt_opts_merge_kms_providers(_mongocrypt_opts_kms_providers_t *dest BSON_ASSERT_PARAM(source); if (source->configured_providers & MONGOCRYPT_KMS_PROVIDER_AWS) { - memcpy(&dest->aws, &source->aws, sizeof(source->aws)); + memcpy(&dest->aws_mut, &source->aws_mut, sizeof(source->aws_mut)); dest->configured_providers |= MONGOCRYPT_KMS_PROVIDER_AWS; } if (source->configured_providers & MONGOCRYPT_KMS_PROVIDER_LOCAL) { - memcpy(&dest->local, &source->local, sizeof(source->local)); + memcpy(&dest->local_mut, &source->local_mut, sizeof(source->local_mut)); dest->configured_providers |= MONGOCRYPT_KMS_PROVIDER_LOCAL; } if (source->configured_providers & MONGOCRYPT_KMS_PROVIDER_AZURE) { - memcpy(&dest->azure, &source->azure, sizeof(source->azure)); + memcpy(&dest->azure_mut, &source->azure_mut, sizeof(source->azure_mut)); dest->configured_providers |= MONGOCRYPT_KMS_PROVIDER_AZURE; } if (source->configured_providers & MONGOCRYPT_KMS_PROVIDER_GCP) { - memcpy(&dest->gcp, &source->gcp, sizeof(source->gcp)); + memcpy(&dest->gcp_mut, &source->gcp_mut, sizeof(source->gcp_mut)); dest->configured_providers |= MONGOCRYPT_KMS_PROVIDER_GCP; } if (source->configured_providers & MONGOCRYPT_KMS_PROVIDER_KMIP) { - memcpy(&dest->kmip, &source->kmip, sizeof(source->kmip)); + memcpy(&dest->kmip_mut, &source->kmip_mut, sizeof(source->kmip_mut)); dest->configured_providers |= MONGOCRYPT_KMS_PROVIDER_KMIP; } /* ensure all providers were copied */ @@ -111,20 +164,20 @@ bool _mongocrypt_opts_kms_providers_validate(_mongocrypt_opts_t *opts, BSON_ASSERT_PARAM(opts); BSON_ASSERT_PARAM(kms_providers); - if (!kms_providers->configured_providers && !kms_providers->need_credentials) { + if (!kms_providers->configured_providers && !kms_providers->need_credentials && kms_providers->named_mut.len == 0) { CLIENT_ERR("no kms provider set"); return false; } if (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AWS) { - if (!kms_providers->aws.access_key_id || !kms_providers->aws.secret_access_key) { + if (!kms_providers->aws_mut.access_key_id || !kms_providers->aws_mut.secret_access_key) { CLIENT_ERR("aws credentials unset"); return false; } } if (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_LOCAL) { - if (_mongocrypt_buffer_empty(&kms_providers->local.key)) { + if (_mongocrypt_buffer_empty(&kms_providers->local_mut.key)) { CLIENT_ERR("local data key unset"); return false; } @@ -223,6 +276,51 @@ bool _mongocrypt_opts_validate(_mongocrypt_opts_t *opts, mongocrypt_status_t *st return _mongocrypt_opts_kms_providers_validate(opts, &opts->kms_providers, status); } +bool _mongocrypt_opts_kms_providers_lookup(const _mongocrypt_opts_kms_providers_t *kms_providers, + const char *kmsid, + mc_kms_creds_t *out) { + *out = (mc_kms_creds_t){0}; + if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AWS) && 0 == strcmp(kmsid, "aws")) { + out->type = MONGOCRYPT_KMS_PROVIDER_AWS; + out->value.aws = kms_providers->aws_mut; + return true; + } + if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AZURE) && 0 == strcmp(kmsid, "azure")) { + out->type = MONGOCRYPT_KMS_PROVIDER_AZURE; + out->value.azure = kms_providers->azure_mut; + return true; + } + + if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_GCP) && 0 == strcmp(kmsid, "gcp")) { + out->type = MONGOCRYPT_KMS_PROVIDER_GCP; + out->value.gcp = kms_providers->gcp_mut; + return true; + } + + if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_LOCAL) && 0 == strcmp(kmsid, "local")) { + out->type = MONGOCRYPT_KMS_PROVIDER_LOCAL; + out->value.local = kms_providers->local_mut; + return true; + } + + if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_KMIP) && 0 == strcmp(kmsid, "kmip")) { + out->type = MONGOCRYPT_KMS_PROVIDER_KMIP; + out->value.kmip = kms_providers->kmip_mut; + return true; + } + + // Check for KMS providers with a name. + for (size_t i = 0; i < kms_providers->named_mut.len; i++) { + mc_kms_creds_with_id_t kcwi = _mc_array_index(&kms_providers->named_mut, mc_kms_creds_with_id_t, i); + if (0 == strcmp(kmsid, kcwi.kmsid)) { + *out = kcwi.creds; + return true; + } + } + + return false; +} + bool _mongocrypt_parse_optional_utf8(const bson_t *bson, const char *dotkey, char **out, mongocrypt_status_t *status) { bson_iter_t iter; bson_iter_t child; @@ -250,6 +348,33 @@ bool _mongocrypt_parse_optional_utf8(const bson_t *bson, const char *dotkey, cha return true; } +bool _mongocrypt_parse_optional_bool(const bson_t *bson, const char *dotkey, bool *out, mongocrypt_status_t *status) { + bson_iter_t iter; + bson_iter_t child; + + BSON_ASSERT_PARAM(bson); + BSON_ASSERT_PARAM(dotkey); + BSON_ASSERT_PARAM(out); + + *out = false; + + if (!bson_iter_init(&iter, bson)) { + CLIENT_ERR("invalid BSON"); + return false; + } + if (!bson_iter_find_descendant(&iter, dotkey, &child)) { + /* Not found. Not an error. */ + return true; + } + if (!BSON_ITER_HOLDS_BOOL(&child)) { + CLIENT_ERR("expected bool %s", dotkey); + return false; + } + + *out = bson_iter_bool(&child); + return true; +} + bool _mongocrypt_parse_required_utf8(const bson_t *bson, const char *dotkey, char **out, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(bson); BSON_ASSERT_PARAM(dotkey); @@ -421,3 +546,454 @@ bool _mongocrypt_check_allowed_fields_va(const bson_t *bson, const char *dotkey, } return true; } + +#define KEY_HELP "Expected `` or `:`. Example: `local` or `local:name`." + +bool mc_kmsid_parse(const char *kmsid, + _mongocrypt_kms_provider_t *type_out, + const char **name_out, + mongocrypt_status_t *status) { + BSON_ASSERT_PARAM(kmsid); + BSON_ASSERT_PARAM(type_out); + BSON_ASSERT_PARAM(name_out); + BSON_ASSERT(status || true); // Optional. + + *type_out = MONGOCRYPT_KMS_PROVIDER_NONE; + *name_out = NULL; + + const char *type_end = strstr(kmsid, ":"); + size_t type_nchars; + + if (type_end == NULL) { + // Parse `kmsid` as ``. + type_nchars = strlen(kmsid); + } else { + // Parse `kmsid` as `:`. + ptrdiff_t diff = type_end - kmsid; + BSON_ASSERT(diff >= 0 && (uint64_t)diff < SIZE_MAX); + type_nchars = (size_t)diff; + } + + if (0 == strncmp("aws", kmsid, type_nchars)) { + *type_out = MONGOCRYPT_KMS_PROVIDER_AWS; + } else if (0 == strncmp("azure", kmsid, type_nchars)) { + *type_out = MONGOCRYPT_KMS_PROVIDER_AZURE; + } else if (0 == strncmp("gcp", kmsid, type_nchars)) { + *type_out = MONGOCRYPT_KMS_PROVIDER_GCP; + } else if (0 == strncmp("kmip", kmsid, type_nchars)) { + *type_out = MONGOCRYPT_KMS_PROVIDER_KMIP; + } else if (0 == strncmp("local", kmsid, type_nchars)) { + *type_out = MONGOCRYPT_KMS_PROVIDER_LOCAL; + } else { + CLIENT_ERR("unrecognized KMS provider `%s`: unrecognized type. " KEY_HELP, kmsid); + return false; + } + + if (type_end != NULL) { + // Parse name. + *name_out = type_end + 1; + if (0 == strlen(*name_out)) { + CLIENT_ERR("unrecognized KMS provider `%s`: empty name. " KEY_HELP, kmsid); + return false; + } + + // Validate name only contains: [a-zA-Z0-9_] + for (const char *cp = *name_out; *cp != '\0'; cp++) { + char c = *cp; + if (c >= 'a' && c <= 'z') { + continue; + } + if (c >= 'A' && c <= 'Z') { + continue; + } + if (c >= '0' && c <= '9') { + continue; + } + if (c == '_') { + continue; + } + CLIENT_ERR("unrecognized KMS provider `%s`: unsupported character `%c`. Must be of the form `:` where `` only contain characters [a-zA-Z0-9_]", + kmsid, + c); + return false; + } + } + return true; +} + +static bool _mongocrypt_opts_kms_provider_local_parse(_mongocrypt_opts_kms_provider_local_t *local, + const char *kmsid, + const bson_t *def, + mongocrypt_status_t *status) { + bool ok = false; + if (!_mongocrypt_parse_required_binary(def, "key", &local->key, status)) { + goto fail; + } + + if (local->key.len != MONGOCRYPT_KEY_LEN) { + CLIENT_ERR("local key must be %d bytes", MONGOCRYPT_KEY_LEN); + goto fail; + } + + if (!_mongocrypt_check_allowed_fields(def, NULL /* root */, status, "key")) { + goto fail; + } + ok = true; +fail: + if (!ok) { + // Wrap error to identify the failing `kmsid`. + CLIENT_ERR("Failed to parse KMS provider `%s`: %s", kmsid, mongocrypt_status_message(status, NULL /* len */)); + } + return ok; +} + +static bool _mongocrypt_opts_kms_provider_azure_parse(_mongocrypt_opts_kms_provider_azure_t *azure, + const char *kmsid, + const bson_t *def, + mongocrypt_status_t *status) { + bool ok = false; + if (!_mongocrypt_parse_optional_utf8(def, "accessToken", &azure->access_token, status)) { + goto done; + } + + if (azure->access_token) { + // Caller provides an accessToken directly + if (!_mongocrypt_check_allowed_fields(def, NULL /* root */, status, "accessToken")) { + goto done; + } + ok = true; + goto done; + } + + // No accessToken given, so we'll need to look one up on our own later + // using the Azure API + + if (!_mongocrypt_parse_required_utf8(def, "tenantId", &azure->tenant_id, status)) { + goto done; + } + + if (!_mongocrypt_parse_required_utf8(def, "clientId", &azure->client_id, status)) { + goto done; + } + + if (!_mongocrypt_parse_required_utf8(def, "clientSecret", &azure->client_secret, status)) { + goto done; + } + + if (!_mongocrypt_parse_optional_endpoint(def, + "identityPlatformEndpoint", + &azure->identity_platform_endpoint, + NULL /* opts */, + status)) { + goto done; + } + + if (!_mongocrypt_check_allowed_fields(def, + NULL /* root */, + status, + "tenantId", + "clientId", + "clientSecret", + "identityPlatformEndpoint")) { + goto done; + } + + ok = true; +done: + if (!ok) { + // Wrap error to identify the failing `kmsid`. + CLIENT_ERR("Failed to parse KMS provider `%s`: %s", kmsid, mongocrypt_status_message(status, NULL /* len */)); + } + return ok; +} + +static bool _mongocrypt_opts_kms_provider_gcp_parse(_mongocrypt_opts_kms_provider_gcp_t *gcp, + const char *kmsid, + const bson_t *def, + mongocrypt_status_t *status) { + bool ok = false; + if (!_mongocrypt_parse_optional_utf8(def, "accessToken", &gcp->access_token, status)) { + goto done; + } + + if (gcp->access_token) { + // Caller provides an accessToken directly + if (!_mongocrypt_check_allowed_fields(def, NULL /* root */, status, "accessToken")) { + goto done; + } + ok = true; + goto done; + } + + // No accessToken given, so we'll need to look one up on our own later + // using the GCP API + + if (!_mongocrypt_parse_required_utf8(def, "email", &gcp->email, status)) { + goto done; + } + + if (!_mongocrypt_parse_required_binary(def, "privateKey", &gcp->private_key, status)) { + goto done; + } + + if (!_mongocrypt_parse_optional_endpoint(def, "endpoint", &gcp->endpoint, NULL /* opts */, status)) { + goto done; + } + + if (!_mongocrypt_check_allowed_fields(def, NULL /* root */, status, "email", "privateKey", "endpoint")) { + goto done; + } + + ok = true; +done: + if (!ok) { + // Wrap error to identify the failing `kmsid`. + CLIENT_ERR("Failed to parse KMS provider `%s`: %s", kmsid, mongocrypt_status_message(status, NULL /* len */)); + } + return ok; +} + +static bool _mongocrypt_opts_kms_provider_aws_parse(_mongocrypt_opts_kms_provider_aws_t *aws, + const char *kmsid, + const bson_t *def, + mongocrypt_status_t *status) { + bool ok = false; + + if (!_mongocrypt_parse_required_utf8(def, "accessKeyId", &aws->access_key_id, status)) { + goto done; + } + if (!_mongocrypt_parse_required_utf8(def, "secretAccessKey", &aws->secret_access_key, status)) { + goto done; + } + + if (!_mongocrypt_parse_optional_utf8(def, "sessionToken", &aws->session_token, status)) { + goto done; + } + + if (!_mongocrypt_check_allowed_fields(def, + NULL /* root */, + status, + "accessKeyId", + "secretAccessKey", + "sessionToken")) { + goto done; + } + + ok = true; +done: + if (!ok) { + // Wrap error to identify the failing `kmsid`. + CLIENT_ERR("Failed to parse KMS provider `%s`: %s", kmsid, mongocrypt_status_message(status, NULL /* len */)); + } + return ok; +} + +static bool _mongocrypt_opts_kms_provider_kmip_parse(_mongocrypt_opts_kms_provider_kmip_t *kmip, + const char *kmsid, + const bson_t *def, + mongocrypt_status_t *status) { + bool ok = false; + + _mongocrypt_endpoint_parse_opts_t opts = {0}; + + opts.allow_empty_subdomain = true; + if (!_mongocrypt_parse_required_endpoint(def, "endpoint", &kmip->endpoint, &opts, status)) { + goto done; + } + + if (!_mongocrypt_check_allowed_fields(def, NULL /* root */, status, "endpoint")) { + goto done; + } + + ok = true; +done: + if (!ok) { + // Wrap error to identify the failing `kmsid`. + CLIENT_ERR("Failed to parse KMS provider `%s`: %s", kmsid, mongocrypt_status_message(status, NULL /* len */)); + } + return ok; +} + +bool _mongocrypt_parse_kms_providers(mongocrypt_binary_t *kms_providers_definition, + _mongocrypt_opts_kms_providers_t *kms_providers, + mongocrypt_status_t *status, + _mongocrypt_log_t *log) { + bson_t as_bson; + bson_iter_t iter; + + BSON_ASSERT_PARAM(kms_providers_definition); + BSON_ASSERT_PARAM(kms_providers); + if (!_mongocrypt_binary_to_bson(kms_providers_definition, &as_bson) || !bson_iter_init(&iter, &as_bson)) { + CLIENT_ERR("invalid BSON"); + return false; + } + + while (bson_iter_next(&iter)) { + const char *field_name; + bson_t field_bson; + + field_name = bson_iter_key(&iter); + if (!mc_iter_document_as_bson(&iter, &field_bson, status)) { + return false; + } + + const char *name; + _mongocrypt_kms_provider_t type; + if (!mc_kmsid_parse(field_name, &type, &name, status)) { + return false; + } + + if (name != NULL) { + // Check if named provider already is configured. + for (size_t i = 0; i < kms_providers->named_mut.len; i++) { + mc_kms_creds_with_id_t kcwi = _mc_array_index(&kms_providers->named_mut, mc_kms_creds_with_id_t, i); + if (0 == strcmp(kcwi.kmsid, field_name)) { + CLIENT_ERR("Got unexpected duplicate entry for KMS provider: `%s`", field_name); + return false; + } + } + // Prohibit configuring with an empty document. Named KMS providers do not support on-demand credentials. + if (bson_empty(&field_bson)) { + CLIENT_ERR("Unexpected empty document for named KMS provider: '%s'. On-demand credentials are not " + "supported for named KMS providers.", + field_name); + return false; + } + switch (type) { + default: + case MONGOCRYPT_KMS_PROVIDER_NONE: { + CLIENT_ERR("Unexpected parsing KMS type: none"); + return false; + } + case MONGOCRYPT_KMS_PROVIDER_AWS: { + _mongocrypt_opts_kms_provider_aws_t aws = {0}; + if (!_mongocrypt_opts_kms_provider_aws_parse(&aws, field_name, &field_bson, status)) { + _mongocrypt_opts_kms_provider_aws_cleanup(&aws); + return false; + } + mc_kms_creds_with_id_t kcwi = {.kmsid = bson_strdup(field_name), + .creds = {.type = type, .value = {.aws = aws}}}; + _mc_array_append_val(&kms_providers->named_mut, kcwi); + break; + } + case MONGOCRYPT_KMS_PROVIDER_LOCAL: { + _mongocrypt_opts_kms_provider_local_t local = { + // specify .key to avoid erroneous missing-braces warning in GCC. Refer: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 + .key = {0}}; + if (!_mongocrypt_opts_kms_provider_local_parse(&local, field_name, &field_bson, status)) { + _mongocrypt_opts_kms_provider_local_cleanup(&local); + return false; + } + mc_kms_creds_with_id_t kcwi = {.kmsid = bson_strdup(field_name), + .creds = {.type = type, .value = {.local = local}}}; + _mc_array_append_val(&kms_providers->named_mut, kcwi); + break; + } + case MONGOCRYPT_KMS_PROVIDER_AZURE: { + _mongocrypt_opts_kms_provider_azure_t azure = {0}; + if (!_mongocrypt_opts_kms_provider_azure_parse(&azure, field_name, &field_bson, status)) { + _mongocrypt_opts_kms_provider_azure_cleanup(&azure); + return false; + } + mc_kms_creds_with_id_t kcwi = {.kmsid = bson_strdup(field_name), + .creds = {.type = type, .value = {.azure = azure}}}; + _mc_array_append_val(&kms_providers->named_mut, kcwi); + break; + } + case MONGOCRYPT_KMS_PROVIDER_GCP: { + _mongocrypt_opts_kms_provider_gcp_t gcp = {0}; + if (!_mongocrypt_opts_kms_provider_gcp_parse(&gcp, field_name, &field_bson, status)) { + _mongocrypt_opts_kms_provider_gcp_cleanup(&gcp); + return false; + } + mc_kms_creds_with_id_t kcwi = {.kmsid = bson_strdup(field_name), + .creds = {.type = type, .value = {.gcp = gcp}}}; + _mc_array_append_val(&kms_providers->named_mut, kcwi); + break; + } + case MONGOCRYPT_KMS_PROVIDER_KMIP: { + _mongocrypt_opts_kms_provider_kmip_t kmip = {0}; + if (!_mongocrypt_opts_kms_provider_kmip_parse(&kmip, field_name, &field_bson, status)) { + _mongocrypt_opts_kms_provider_kmip_cleanup(&kmip); + return false; + } + mc_kms_creds_with_id_t kcwi = {.kmsid = bson_strdup(field_name), + .creds = {.type = type, .value = {.kmip = kmip}}}; + _mc_array_append_val(&kms_providers->named_mut, kcwi); + break; + } + } + } else if (0 == strcmp(field_name, "azure") && bson_empty(&field_bson)) { + kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_AZURE; + } else if (0 == strcmp(field_name, "azure")) { + if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AZURE)) { + CLIENT_ERR("azure KMS provider already set"); + return false; + } + + if (!_mongocrypt_opts_kms_provider_azure_parse(&kms_providers->azure_mut, + field_name, + &field_bson, + status)) { + return false; + } + kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_AZURE; + } else if (0 == strcmp(field_name, "gcp") && bson_empty(&field_bson)) { + kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_GCP; + } else if (0 == strcmp(field_name, "gcp")) { + if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_GCP)) { + CLIENT_ERR("gcp KMS provider already set"); + return false; + } + if (!_mongocrypt_opts_kms_provider_gcp_parse(&kms_providers->gcp_mut, field_name, &field_bson, status)) { + return false; + } + kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_GCP; + } else if (0 == strcmp(field_name, "local") && bson_empty(&field_bson)) { + kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_LOCAL; + } else if (0 == strcmp(field_name, "local")) { + if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_LOCAL)) { + CLIENT_ERR("local KMS provider already set"); + return false; + } + if (!_mongocrypt_opts_kms_provider_local_parse(&kms_providers->local_mut, + field_name, + &field_bson, + status)) { + return false; + } + kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_LOCAL; + } else if (0 == strcmp(field_name, "aws") && bson_empty(&field_bson)) { + kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_AWS; + } else if (0 == strcmp(field_name, "aws")) { + if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AWS)) { + CLIENT_ERR("aws KMS provider already set"); + return false; + } + if (!_mongocrypt_opts_kms_provider_aws_parse(&kms_providers->aws_mut, field_name, &field_bson, status)) { + return false; + } + kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_AWS; + } else if (0 == strcmp(field_name, "kmip") && bson_empty(&field_bson)) { + kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_KMIP; + } else if (0 == strcmp(field_name, "kmip")) { + if (!_mongocrypt_opts_kms_provider_kmip_parse(&kms_providers->kmip_mut, field_name, &field_bson, status)) { + return false; + } + kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_KMIP; + } else { + CLIENT_ERR("unsupported KMS provider: %s", field_name); + return false; + } + } + + if (log && log->trace_enabled) { + char *as_str = bson_as_json(&as_bson, NULL); + _mongocrypt_log(log, MONGOCRYPT_LOG_LEVEL_TRACE, "%s (%s=\"%s\")", BSON_FUNC, "kms_providers", as_str); + bson_free(as_str); + } + + return true; +} diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h index 15ec363..f14ed7b 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h @@ -39,7 +39,7 @@ #define CLIENT_ERR_W_CODE(code, ...) _mongocrypt_set_error(status, MONGOCRYPT_STATUS_ERROR_CLIENT, code, __VA_ARGS__) -#define CLIENT_ERR(...) CLIENT_ERR_W_CODE(MONGOCRYPT_GENERIC_ERROR_CODE, __VA_ARGS__) +#define CLIENT_ERR(fmt, ...) CLIENT_ERR_W_CODE(MONGOCRYPT_GENERIC_ERROR_CODE, fmt, ##__VA_ARGS__) #define KMS_ERR_W_CODE(code, ...) _mongocrypt_set_error(status, MONGOCRYPT_STATUS_ERROR_KMS, code, __VA_ARGS__) @@ -49,9 +49,6 @@ #define MONGOCRYPT_DATA_AND_LEN(x) ((uint8_t *)x), (sizeof(x) / sizeof((x)[0]) - 1) -/* TODO: remove after integrating into libmongoc */ -#define BSON_SUBTYPE_ENCRYPTED 6 - /* TODO: Move these to mongocrypt-log-private.h? */ const char *tmp_json(const bson_t *bson); @@ -123,8 +120,7 @@ struct _mongocrypt_t { _mongocrypt_crypto_t *crypto; /* A counter, protected by mutex, for generating unique context ids */ uint32_t ctx_counter; - _mongocrypt_cache_oauth_t *cache_oauth_azure; - _mongocrypt_cache_oauth_t *cache_oauth_gcp; + mc_mapof_kmsid_to_token_t *cache_oauth; /// A CSFLE DLL vtable, initialized by mongocrypt_init _mongo_crypt_v1_vtable csfle; /// Pointer to the global csfle_lib object. Should not be freed directly. @@ -154,18 +150,15 @@ char *_mongocrypt_new_string_from_bytes(const void *in, int len); char *_mongocrypt_new_json_string_from_binary(mongocrypt_binary_t *binary); -bool _mongocrypt_parse_kms_providers(mongocrypt_binary_t *kms_providers_definition, - _mongocrypt_opts_kms_providers_t *kms_providers, - mongocrypt_status_t *status, - _mongocrypt_log_t *log); - /* _mongocrypt_needs_credentials returns true if @crypt was configured to * request credentials for any KMS provider. */ bool _mongocrypt_needs_credentials(mongocrypt_t *crypt); /* _mongocrypt_needs_credentials returns true if @crypt was configured to - * request credentials for @provider. */ -bool _mongocrypt_needs_credentials_for_provider(mongocrypt_t *crypt, _mongocrypt_kms_provider_t provider); + * request credentials for @provider and optional @name. @name may be NULL. */ +bool _mongocrypt_needs_credentials_for_provider(mongocrypt_t *crypt, + _mongocrypt_kms_provider_t provider, + const char *name); /** * Enable/disable the use of FLE2v2 payload types for write. diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-util.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-util.c index 205ce26..202c495 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt-util.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt-util.c @@ -81,7 +81,7 @@ current_module_result current_module_path(void) { #elif defined(_GNU_SOURCE) || defined(_DARWIN_C_SOURCE) || defined(__FreeBSD__) // Darwin/BSD/glibc define extensions for finding dynamic library info from // the address of a symbol. - Dl_info info; + Dl_info info = {0}; int rc = dladdr((const void *)current_module_path, &info); if (rc == 0) { // Failed to resolve the symbol @@ -90,7 +90,8 @@ current_module_result current_module_path(void) { ret_str = mstr_copy_cstr(info.dli_fname); } #else -#error "Don't know how to get the module path on this platform" + // Not supported on this system. + ret_error = ENOSYS; #endif return (current_module_result){.path = ret_str, .error = ret_error}; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c b/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c index 9ad6d9c..be73f5b 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c @@ -119,8 +119,7 @@ mongocrypt_t *mongocrypt_new(void) { // Default to using FLEv2 (aka QEv2) crypt->opts.use_fle2_v2 = true; crypt->ctx_counter = 1; - crypt->cache_oauth_azure = _mongocrypt_cache_oauth_new(); - crypt->cache_oauth_gcp = _mongocrypt_cache_oauth_new(); + crypt->cache_oauth = mc_mapof_kmsid_to_token_new(); crypt->csfle = (_mongo_crypt_v1_vtable){.okay = false}; static mlib_once_flag init_flag = MLIB_ONCE_INITIALIZER; @@ -154,6 +153,13 @@ bool mongocrypt_setopt_fle2v2(mongocrypt_t *crypt, bool enable) { return true; } +bool mongocrypt_setopt_use_range_v2(mongocrypt_t *crypt) { + ASSERT_MONGOCRYPT_PARAM_UNINIT(crypt); + + // Nothing to do. As of MONGOCRYPT-661, rangeV2 is the default. + return true; +} + bool mongocrypt_setopt_log_handler(mongocrypt_t *crypt, mongocrypt_log_fn_t log_fn, void *log_ctx) { ASSERT_MONGOCRYPT_PARAM_UNINIT(crypt); crypt->opts.log_fn = log_fn; @@ -178,14 +184,14 @@ bool mongocrypt_setopt_kms_provider_aws(mongocrypt_t *crypt, if (!_mongocrypt_validate_and_copy_string(aws_access_key_id, aws_access_key_id_len, - &kms_providers->aws.access_key_id)) { + &kms_providers->aws_mut.access_key_id)) { CLIENT_ERR("invalid aws access key id"); return false; } if (!_mongocrypt_validate_and_copy_string(aws_secret_access_key, aws_secret_access_key_len, - &kms_providers->aws.secret_access_key)) { + &kms_providers->aws_mut.secret_access_key)) { CLIENT_ERR("invalid aws secret access key"); return false; } @@ -196,11 +202,11 @@ bool mongocrypt_setopt_kms_provider_aws(mongocrypt_t *crypt, "%s (%s=\"%s\", %s=%d, %s=\"%s\", %s=%d)", BSON_FUNC, "aws_access_key_id", - kms_providers->aws.access_key_id, + kms_providers->aws_mut.access_key_id, "aws_access_key_id_len", aws_access_key_id_len, "aws_secret_access_key", - kms_providers->aws.secret_access_key, + kms_providers->aws_mut.secret_access_key, "aws_secret_access_key_len", aws_secret_access_key_len); } @@ -345,7 +351,7 @@ bool mongocrypt_setopt_kms_provider_local(mongocrypt_t *crypt, mongocrypt_binary bson_free(key_val); } - _mongocrypt_buffer_copy_from_binary(&kms_providers->local.key, key); + _mongocrypt_buffer_copy_from_binary(&kms_providers->local_mut.key, key); kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_LOCAL; return true; } @@ -365,7 +371,7 @@ typedef struct { * * @param status is an optional status to set an error message if `mcr_dll_open` fails. */ -static _loaded_csfle _try_load_csfle(const char *filepath, _mongocrypt_log_t *log, mongocrypt_status_t *status) { +static _loaded_csfle _try_load_csfle(const char *filepath, mongocrypt_status_t *status, _mongocrypt_log_t *log) { // Try to open the dynamic lib mcr_dll lib = mcr_dll_open(filepath); // Check for errors, which are represented by strings @@ -479,7 +485,7 @@ static _loaded_csfle _try_find_csfle(mongocrypt_t *crypt) { // Do not allow a plain filename to go through, as that will cause the // DLL load to search the system. mstr_assign(&csfle_cand_filepath, mpath_absolute(csfle_cand_filepath.view, MPATH_NATIVE)); - candidate_csfle = _try_load_csfle(csfle_cand_filepath.data, &crypt->log, crypt->status); + candidate_csfle = _try_load_csfle(csfle_cand_filepath.data, crypt->status, &crypt->log); } } else { // No override path was specified, so try to find it on the provided @@ -501,7 +507,7 @@ static _loaded_csfle _try_find_csfle(mongocrypt_t *crypt) { } } // Try to load the file: - candidate_csfle = _try_load_csfle(csfle_cand_filepath.data, &crypt->log, NULL /* status */); + candidate_csfle = _try_load_csfle(csfle_cand_filepath.data, NULL /* status */, &crypt->log); if (candidate_csfle.okay) { // Stop searching: break; @@ -552,6 +558,14 @@ static bool _validate_csfle_singleton(mongocrypt_t *crypt, _loaded_csfle found) BSON_ASSERT_PARAM(crypt); + if (!mcr_dll_path_supported()) { + _mongocrypt_log(&crypt->log, + MONGOCRYPT_LOG_LEVEL_WARNING, + "Cannot get path of loaded library on this platform. Skipping validation to ensure " + "exactly one csfle library is loaded."); + return true; + } + status = crypt->status; // Path to the existing loaded csfle: @@ -884,6 +898,14 @@ bool mongocrypt_init(mongocrypt_t *crypt) { return _try_enable_csfle(crypt); } +bool mongocrypt_is_crypto_available(void) { +#ifdef MONGOCRYPT_ENABLE_CRYPTO + return true; +#else + return false; +#endif +} + bool mongocrypt_status(mongocrypt_t *crypt, mongocrypt_status_t *out) { BSON_ASSERT_PARAM(crypt); @@ -912,8 +934,7 @@ void mongocrypt_destroy(mongocrypt_t *crypt) { _mongocrypt_log_cleanup(&crypt->log); mongocrypt_status_destroy(crypt->status); bson_free(crypt->crypto); - _mongocrypt_cache_oauth_destroy(crypt->cache_oauth_azure); - _mongocrypt_cache_oauth_destroy(crypt->cache_oauth_gcp); + mc_mapof_kmsid_to_token_destroy(crypt->cache_oauth); if (crypt->csfle.okay) { _csfle_drop_global_ref(); @@ -1097,227 +1118,6 @@ bool mongocrypt_setopt_kms_providers(mongocrypt_t *crypt, mongocrypt_binary_t *k &crypt->log); } -bool _mongocrypt_parse_kms_providers(mongocrypt_binary_t *kms_providers_definition, - _mongocrypt_opts_kms_providers_t *kms_providers, - mongocrypt_status_t *status, - _mongocrypt_log_t *log) { - bson_t as_bson; - bson_iter_t iter; - - BSON_ASSERT_PARAM(kms_providers_definition); - BSON_ASSERT_PARAM(kms_providers); - if (!_mongocrypt_binary_to_bson(kms_providers_definition, &as_bson) || !bson_iter_init(&iter, &as_bson)) { - CLIENT_ERR("invalid BSON"); - return false; - } - - while (bson_iter_next(&iter)) { - const char *field_name; - bson_t field_bson; - - field_name = bson_iter_key(&iter); - if (!mc_iter_document_as_bson(&iter, &field_bson, status)) { - return false; - } - - if (0 == strcmp(field_name, "azure") && bson_empty(&field_bson)) { - kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_AZURE; - } else if (0 == strcmp(field_name, "azure")) { - if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_AZURE)) { - CLIENT_ERR("azure KMS provider already set"); - return false; - } - - if (!_mongocrypt_parse_optional_utf8(&as_bson, - "azure.accessToken", - &kms_providers->azure.access_token, - status)) { - return false; - } - - if (kms_providers->azure.access_token) { - // Caller provides an accessToken directly - if (!_mongocrypt_check_allowed_fields(&as_bson, "azure", status, "accessToken")) { - return false; - } - kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_AZURE; - continue; - } - - // No accessToken given, so we'll need to look one up on our own later - // using the Azure API - - if (!_mongocrypt_parse_required_utf8(&as_bson, "azure.tenantId", &kms_providers->azure.tenant_id, status)) { - return false; - } - - if (!_mongocrypt_parse_required_utf8(&as_bson, "azure.clientId", &kms_providers->azure.client_id, status)) { - return false; - } - - if (!_mongocrypt_parse_required_utf8(&as_bson, - "azure.clientSecret", - &kms_providers->azure.client_secret, - status)) { - return false; - } - - if (!_mongocrypt_parse_optional_endpoint(&as_bson, - "azure.identityPlatformEndpoint", - &kms_providers->azure.identity_platform_endpoint, - NULL /* opts */, - status)) { - return false; - } - - if (!_mongocrypt_check_allowed_fields(&as_bson, - "azure", - status, - "tenantId", - "clientId", - "clientSecret", - "identityPlatformEndpoint")) { - return false; - } - kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_AZURE; - } else if (0 == strcmp(field_name, "gcp") && bson_empty(&field_bson)) { - kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_GCP; - } else if (0 == strcmp(field_name, "gcp")) { - if (0 != (kms_providers->configured_providers & MONGOCRYPT_KMS_PROVIDER_GCP)) { - CLIENT_ERR("gcp KMS provider already set"); - return false; - } - - if (!_mongocrypt_parse_optional_utf8(&as_bson, - "gcp.accessToken", - &kms_providers->gcp.access_token, - status)) { - return false; - } - - if (NULL != kms_providers->gcp.access_token) { - /* "gcp" document has form: - * { - * "accessToken": - * } - */ - if (!_mongocrypt_check_allowed_fields(&as_bson, "gcp", status, "accessToken")) { - return false; - } - kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_GCP; - continue; - } - - /* "gcp" document has form: - * { - * "email": - * "privateKey": - * } - */ - if (!_mongocrypt_parse_required_utf8(&as_bson, "gcp.email", &kms_providers->gcp.email, status)) { - return false; - } - - if (!_mongocrypt_parse_required_binary(&as_bson, - "gcp.privateKey", - &kms_providers->gcp.private_key, - status)) { - return false; - } - - if (!_mongocrypt_parse_optional_endpoint(&as_bson, - "gcp.endpoint", - &kms_providers->gcp.endpoint, - NULL /* opts */, - status)) { - return false; - } - - if (!_mongocrypt_check_allowed_fields(&as_bson, "gcp", status, "email", "privateKey", "endpoint")) { - return false; - } - kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_GCP; - } else if (0 == strcmp(field_name, "local") && bson_empty(&field_bson)) { - kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_LOCAL; - } else if (0 == strcmp(field_name, "local")) { - if (!_mongocrypt_parse_required_binary(&as_bson, "local.key", &kms_providers->local.key, status)) { - return false; - } - - if (kms_providers->local.key.len != MONGOCRYPT_KEY_LEN) { - CLIENT_ERR("local key must be %d bytes", MONGOCRYPT_KEY_LEN); - return false; - } - - if (!_mongocrypt_check_allowed_fields(&as_bson, "local", status, "key")) { - return false; - } - kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_LOCAL; - } else if (0 == strcmp(field_name, "aws") && bson_empty(&field_bson)) { - kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_AWS; - } else if (0 == strcmp(field_name, "aws")) { - if (!_mongocrypt_parse_required_utf8(&as_bson, - "aws.accessKeyId", - &kms_providers->aws.access_key_id, - status)) { - return false; - } - if (!_mongocrypt_parse_required_utf8(&as_bson, - "aws.secretAccessKey", - &kms_providers->aws.secret_access_key, - status)) { - return false; - } - - if (!_mongocrypt_parse_optional_utf8(&as_bson, - "aws.sessionToken", - &kms_providers->aws.session_token, - status)) { - return false; - } - - if (!_mongocrypt_check_allowed_fields(&as_bson, - "aws", - status, - "accessKeyId", - "secretAccessKey", - "sessionToken")) { - return false; - } - kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_AWS; - } else if (0 == strcmp(field_name, "kmip") && bson_empty(&field_bson)) { - kms_providers->need_credentials |= MONGOCRYPT_KMS_PROVIDER_KMIP; - } else if (0 == strcmp(field_name, "kmip")) { - _mongocrypt_endpoint_parse_opts_t opts = {0}; - - opts.allow_empty_subdomain = true; - if (!_mongocrypt_parse_required_endpoint(&as_bson, - "kmip.endpoint", - &kms_providers->kmip.endpoint, - &opts, - status)) { - return false; - } - - if (!_mongocrypt_check_allowed_fields(&as_bson, "kmip", status, "endpoint")) { - return false; - } - kms_providers->configured_providers |= MONGOCRYPT_KMS_PROVIDER_KMIP; - } else { - CLIENT_ERR("unsupported KMS provider: %s", field_name); - return false; - } - } - - if (log && log->trace_enabled) { - char *as_str = bson_as_json(&as_bson, NULL); - _mongocrypt_log(log, MONGOCRYPT_LOG_LEVEL_TRACE, "%s (%s=\"%s\")", BSON_FUNC, "kms_providers", as_str); - bson_free(as_str); - } - - return true; -} - void mongocrypt_setopt_append_crypt_shared_lib_search_path(mongocrypt_t *crypt, const char *path) { BSON_ASSERT_PARAM(crypt); BSON_ASSERT_PARAM(path); @@ -1343,6 +1143,12 @@ void mongocrypt_setopt_use_need_kms_credentials_state(mongocrypt_t *crypt) { crypt->opts.use_need_kms_credentials_state = true; } +void mongocrypt_setopt_use_need_mongo_collinfo_with_db_state(mongocrypt_t *crypt) { + BSON_ASSERT_PARAM(crypt); + + crypt->opts.use_need_mongo_collinfo_with_db_state = true; +} + void mongocrypt_setopt_set_crypt_shared_lib_path_override(mongocrypt_t *crypt, const char *path) { BSON_ASSERT_PARAM(crypt); BSON_ASSERT_PARAM(path); @@ -1360,9 +1166,16 @@ bool _mongocrypt_needs_credentials(mongocrypt_t *crypt) { return crypt->opts.kms_providers.need_credentials != 0; } -bool _mongocrypt_needs_credentials_for_provider(mongocrypt_t *crypt, _mongocrypt_kms_provider_t provider) { +bool _mongocrypt_needs_credentials_for_provider(mongocrypt_t *crypt, + _mongocrypt_kms_provider_t provider, + const char *name) { BSON_ASSERT_PARAM(crypt); + if (name != NULL) { + // Named KMS providers do not support on-demand credentials. + return false; + } + if (!crypt->opts.use_need_kms_credentials_state) { return false; } diff --git a/ext/libmongocrypt/libmongocrypt/src/mongocrypt.h b/ext/libmongocrypt/libmongocrypt/src/mongocrypt.h index e4ca0b1..41c2c0e 100644 --- a/ext/libmongocrypt/libmongocrypt/src/mongocrypt.h +++ b/ext/libmongocrypt/libmongocrypt/src/mongocrypt.h @@ -48,6 +48,17 @@ MONGOCRYPT_EXPORT const char *mongocrypt_version(uint32_t *len); +/** + * Returns true if libmongocrypt was built with native crypto support. + * + * If libmongocrypt was not built with native crypto support, setting crypto + * hooks is required. + * + * @returns True if libmongocrypt was built with native crypto support. + */ +MONGOCRYPT_EXPORT +bool mongocrypt_is_crypto_available(void); + /** * A non-owning view of a byte buffer. * @@ -69,8 +80,14 @@ const char *mongocrypt_version(uint32_t *len); * mongocrypt_ctx_mongo_op guarantees that the viewed data of * mongocrypt_binary_t is valid until the parent ctx is destroyed with @ref * mongocrypt_ctx_destroy. + * + * The `mongocrypt_binary_t` struct definition is public. + * Consumers may rely on the struct layout. */ -typedef struct _mongocrypt_binary_t mongocrypt_binary_t; +typedef struct _mongocrypt_binary_t { + void *data; + uint32_t len; +} mongocrypt_binary_t; /** * Create a new non-owning view of a buffer (data + length). @@ -456,6 +473,18 @@ void mongocrypt_setopt_set_crypt_shared_lib_path_override(mongocrypt_t *crypt, c MONGOCRYPT_EXPORT void mongocrypt_setopt_use_need_kms_credentials_state(mongocrypt_t *crypt); +/** + * @brief Opt-into handling the MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB state. + * + * A context enters the MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB state when + * processing a `bulkWrite` command. The target database of the `bulkWrite` may differ from the command database + * ("admin"). + * + * @param[in] crypt The @ref mongocrypt_t object to update + */ +MONGOCRYPT_EXPORT +void mongocrypt_setopt_use_need_mongo_collinfo_with_db_state(mongocrypt_t *crypt); + /** * Initialize new @ref mongocrypt_t object. * @@ -657,10 +686,9 @@ bool mongocrypt_ctx_setopt_algorithm(mongocrypt_ctx_t *ctx, const char *algorith #define MONGOCRYPT_ALGORITHM_INDEXED_STR "Indexed" /// String constant for setopt_algorithm "Unindexed" explicit encryption #define MONGOCRYPT_ALGORITHM_UNINDEXED_STR "Unindexed" -/// String constant for setopt_algorithm "rangePreview" explicit encryption -/// NOTE: The RangePreview algorithm is experimental only. It is not intended -/// for public use. -#define MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR "RangePreview" +// DEPRECATED: support "RangePreview" has been removed in favor of "range". +#define MONGOCRYPT_ALGORITHM_RANGEPREVIEW_DEPRECATED_STR "RangePreview" +#define MONGOCRYPT_ALGORITHM_RANGE_STR "Range" /** * Identify the AWS KMS master key to use for creating a data key. @@ -849,9 +877,7 @@ bool mongocrypt_ctx_explicit_encrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_bina /** * Explicit helper method to encrypt a Match Expression or Aggregate Expression. * Contexts created for explicit encryption will not go through mongocryptd. - * Requires query_type to be "rangePreview". - * NOTE: The RangePreview algorithm is experimental only. It is not intended for - * public use. + * Requires query_type to be "range". * * This method expects the passed-in BSON to be of the form: * { "v" : FLE2RangeFindDriverSpec } @@ -948,9 +974,10 @@ bool mongocrypt_ctx_rewrap_many_datakey_init(mongocrypt_ctx_t *ctx, mongocrypt_b */ typedef enum { MONGOCRYPT_CTX_ERROR = 0, - MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /* run on main MongoClient */ - MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /* run on mongocryptd. */ - MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /* run on key vault */ + MONGOCRYPT_CTX_NEED_MONGO_COLLINFO = 1, /* run on main MongoClient */ + MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB = 8, /* run on main MongoClient */ + MONGOCRYPT_CTX_NEED_MONGO_MARKINGS = 2, /* run on mongocryptd. */ + MONGOCRYPT_CTX_NEED_MONGO_KEYS = 3, /* run on key vault */ MONGOCRYPT_CTX_NEED_KMS = 4, MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS = 7, /* fetch/renew KMS credentials */ MONGOCRYPT_CTX_READY = 5, /* ready for encryption/decryption */ @@ -971,7 +998,7 @@ mongocrypt_ctx_state_t mongocrypt_ctx_state(mongocrypt_ctx_t *ctx); * is in MONGOCRYPT_CTX_NEED_MONGO_* states. * * @p op_bson is a BSON document to be used for the operation. - * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a listCollections filter. + * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO(_WITH_DB) it is a listCollections filter. * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a find filter. * - For MONGOCRYPT_CTX_NEED_MONGO_MARKINGS it is a command to send to * mongocryptd. @@ -989,13 +1016,29 @@ mongocrypt_ctx_state_t mongocrypt_ctx_state(mongocrypt_ctx_t *ctx); MONGOCRYPT_EXPORT bool mongocrypt_ctx_mongo_op(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *op_bson); +/** + * Get the database to run the mongo operation. + * + * Only applies when mongocrypt_ctx_t is in the state: + * MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB. + * + * The lifetime of the returned string is tied to the lifetime of @p ctx. It is + * valid until @ref mongocrypt_ctx_destroy is called. + * + * @param[in] ctx The @ref mongocrypt_ctx_t object. + * @returns A string or NULL. If NULL, an error status is set. Retrieve it with + * @ref mongocrypt_ctx_status + */ +MONGOCRYPT_EXPORT +const char *mongocrypt_ctx_mongo_db(mongocrypt_ctx_t *ctx); + /** * Feed a BSON reply or result when mongocrypt_ctx_t is in * MONGOCRYPT_CTX_NEED_MONGO_* states. This may be called multiple times * depending on the operation. * * reply is a BSON document result being fed back for this operation. - * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO it is a doc from a listCollections + * - For MONGOCRYPT_CTX_NEED_MONGO_COLLINFO(_WITH_DB) it is a doc from a listCollections * cursor. (Note, if listCollections returned no result, do not call this * function.) * - For MONGOCRYPT_CTX_NEED_MONGO_KEYS it is a doc from a find cursor. @@ -1305,8 +1348,7 @@ bool mongocrypt_setopt_crypto_hooks(mongocrypt_t *crypt, * operation. * @param[in] aes_256_ctr_decrypt The crypto callback function for decrypt * operation. - * @param[in] ctx A context passed as an argument to the crypto callback - * every invocation. + * @param[in] ctx Unused. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status @@ -1326,8 +1368,7 @@ bool mongocrypt_setopt_aes_256_ctr(mongocrypt_t *crypt, * @param[in] crypt The @ref mongocrypt_t object. * @param[in] aes_256_ecb_encrypt The crypto callback function for encrypt * operation. - * @param[in] ctx A context passed as an argument to the crypto callback - * every invocation. + * @param[in] ctx Unused. * @pre @ref mongocrypt_init has not been called on @p crypt. * @returns A boolean indicating success. If false, an error status is set. * Retrieve it with @ref mongocrypt_status @@ -1370,6 +1411,17 @@ bool mongocrypt_setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(mongocrypt_t *crypt, MONGOCRYPT_EXPORT void mongocrypt_setopt_bypass_query_analysis(mongocrypt_t *crypt); +/** + * DEPRECATED: Use of `mongocrypt_setopt_use_range_v2` is deprecated. Range V2 is always enabled. + * + * @param[in] crypt The @ref mongocrypt_t object. + * + * @returns A boolean indicating success. If false, an error status is set. + * Retrieve it with @ref mongocrypt_status + */ +MONGOCRYPT_EXPORT +bool mongocrypt_setopt_use_range_v2(mongocrypt_t *crypt); + /** * Set the contention factor used for explicit encryption. * The contention factor is only used for indexed Queryable Encryption. @@ -1415,16 +1467,15 @@ MONGOCRYPT_EXPORT bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t *ctx, const char *query_type, int len); /** - * Set options for explicit encryption with the "rangePreview" algorithm. - * NOTE: The RangePreview algorithm is experimental only. It is not intended for - * public use. + * Set options for explicit encryption with the "range" algorithm. * * @p opts is a BSON document of the form: * { * "min": Optional, * "max": Optional, * "sparsity": Int64, - * "precision": Optional + * "precision": Optional, + * "trimFactor": Optional * } * * @param[in] ctx The @ref mongocrypt_ctx_t object. @@ -1438,8 +1489,8 @@ bool mongocrypt_ctx_setopt_algorithm_range(mongocrypt_ctx_t *ctx, mongocrypt_bin /// String constants for setopt_query_type #define MONGOCRYPT_QUERY_TYPE_EQUALITY_STR "equality" -// NOTE: The RangePreview algorithm is experimental only. It is not intended for -// public use. -#define MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR "rangePreview" +// DEPRECATED: Support "rangePreview" has been removed in favor of "range". +#define MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED_STR "rangePreview" +#define MONGOCRYPT_QUERY_TYPE_RANGE_STR "range" #endif /* MONGOCRYPT_H */ diff --git a/ext/libmongocrypt/libmongocrypt/src/os_posix/os_dll.c b/ext/libmongocrypt/libmongocrypt/src/os_posix/os_dll.c index 425f39f..21149e6 100644 --- a/ext/libmongocrypt/libmongocrypt/src/os_posix/os_dll.c +++ b/ext/libmongocrypt/libmongocrypt/src/os_posix/os_dll.c @@ -95,26 +95,42 @@ mcr_dll_path_result mcr_dll_path(mcr_dll dll) { return (mcr_dll_path_result){.error_string = mstr_copy_cstr("Handle not found in loaded modules")}; } +bool mcr_dll_path_supported(void) { + return true; +} + #elif defined(__linux__) || defined(__FreeBSD__) #include mcr_dll_path_result mcr_dll_path(mcr_dll dll) { - struct link_map *map; + struct link_map *map = NULL; int rc = dlinfo(dll._native_handle, RTLD_DI_LINKMAP, &map); if (rc == 0) { + assert(NULL != map); return (mcr_dll_path_result){.path = mstr_copy_cstr(map->l_name)}; } else { return (mcr_dll_path_result){.error_string = mstr_copy_cstr(dlerror())}; } } +bool mcr_dll_path_supported(void) { + return true; +} + #elif defined(_WIN32) // Handled in os_win/os_dll.c #else -#error "Don't know how to do mcr_dll_path() on this platform" +mcr_dll_path_result mcr_dll_path(mcr_dll dll) { + return (mcr_dll_path_result){.error_string = + mstr_copy_cstr("Don't know how to do mcr_dll_path() on this platform")}; +} + +bool mcr_dll_path_supported(void) { + return false; +} #endif diff --git a/ext/libmongocrypt/libmongocrypt/src/os_win/os_dll.c b/ext/libmongocrypt/libmongocrypt/src/os_win/os_dll.c index b011794..e6e4f1b 100644 --- a/ext/libmongocrypt/libmongocrypt/src/os_win/os_dll.c +++ b/ext/libmongocrypt/libmongocrypt/src/os_win/os_dll.c @@ -76,4 +76,8 @@ mcr_dll_path_result mcr_dll_path(mcr_dll dll) { }; } +bool mcr_dll_path_supported(void) { + return true; +} + #endif diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/bypassQueryAnalysis/payload.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/bypassQueryAnalysis/payload.json new file mode 100644 index 0000000..97124c5 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/bypassQueryAnalysis/payload.json @@ -0,0 +1,53 @@ +{ + "bulkWrite": { + "$numberInt": "1" + }, + "ops": [ + { + "insert": { + "$numberInt": "0" + }, + "document": { + "plainText": "sample", + "encrypted": { + "$numberInt": "123" + } + } + } + ], + "$db": "admin", + "nsInfo": [ + { + "ns": "db.test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "equality", + "contention": { + "$numberLong": "0" + } + } + } + ] + } + } + } + } + ] +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/jsonSchema/cmd-to-mongocryptd.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/jsonSchema/cmd-to-mongocryptd.json new file mode 100644 index 0000000..2a5e60c --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/jsonSchema/cmd-to-mongocryptd.json @@ -0,0 +1,23 @@ +{ + "bulkWrite": { + "$numberInt": "1" + }, + "ops": [ + { + "insert": 0, + "document": { + "plainText": "sample", + "encrypted": { + "$numberInt": "123" + } + } + } + ], + "nsInfo": [ + { + "ns": "db.test" + } + ], + "jsonSchema": {}, + "isRemoteSchema": false +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/jsonSchema/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/jsonSchema/cmd.json new file mode 100644 index 0000000..2c0b515 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/jsonSchema/cmd.json @@ -0,0 +1,20 @@ +{ + "bulkWrite": 1, + "ops": [ + { + "insert": 0, + "document": { + "plainText": "sample", + "encrypted": { + "$numberInt": "123" + } + } + } + ], + "nsInfo": [ + { + "ns": "db.test" + } + ], + "$db": "admin" +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/cmd-to-mongocryptd.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/cmd-to-mongocryptd.json new file mode 100644 index 0000000..7d01df7 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/cmd-to-mongocryptd.json @@ -0,0 +1,50 @@ +{ + "bulkWrite": { + "$numberInt": "1" + }, + "ops": [ + { + "insert": 0, + "document": { + "plainText": "sample", + "encrypted": { + "$numberInt": "123" + } + } + } + ], + "nsInfo": [ + { + "ns": "db.test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "equality", + "contention": { + "$numberLong": "0" + } + } + } + ] + } + } + } + } + ] +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/cmd.json new file mode 100644 index 0000000..2c0b515 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/cmd.json @@ -0,0 +1,20 @@ +{ + "bulkWrite": 1, + "ops": [ + { + "insert": 0, + "document": { + "plainText": "sample", + "encrypted": { + "$numberInt": "123" + } + } + } + ], + "nsInfo": [ + { + "ns": "db.test" + } + ], + "$db": "admin" +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/collinfo.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/collinfo.json new file mode 100644 index 0000000..ef03d4e --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/collinfo.json @@ -0,0 +1,44 @@ +{ + "name": "test", + "type": "collection", + "options": { + "encryptedFields": { + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "equality", + "contention": { + "$numberLong": "0" + } + } + } + ] + } + }, + "info": { + "readOnly": false, + "uuid": { + "$binary": { + "base64": "4z9fIUN+Sh2WeH/aySC+OA==", + "subType": "04" + } + } + }, + "idIndex": { + "v": 2, + "key": { + "_id": 1 + }, + "name": "_id_" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/encrypted-field-map.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/encrypted-field-map.json new file mode 100644 index 0000000..e7617ad --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/encrypted-field-map.json @@ -0,0 +1,24 @@ +{ + "db.test": { + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "equality", + "contention": { + "$numberLong": "0" + } + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/encrypted-payload-pattern.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/encrypted-payload-pattern.json new file mode 100644 index 0000000..1dfa8b6 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/encrypted-payload-pattern.json @@ -0,0 +1,53 @@ +{ + "bulkWrite": { + "$numberInt": "1" + }, + "ops": [ + { + "insert": { + "$numberInt": "0" + }, + "document": { + "plainText": "sample", + "encrypted": { + "$$type": "binData" + } + } + } + ], + "nsInfo": [ + { + "ns": "db.test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "equality", + "contention": { + "$numberLong": "0" + } + } + } + ] + } + } + } + } + ], + "$db": "admin" +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/mongocryptd-reply.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/mongocryptd-reply.json new file mode 100644 index 0000000..5ad29aa --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/simple/mongocryptd-reply.json @@ -0,0 +1,62 @@ +{ + "hasEncryptionPlaceholders": true, + "schemaRequiresEncryption": true, + "result": { + "bulkWrite": { + "$numberInt": "1" + }, + "ops": [ + { + "insert": { + "$numberInt": "0" + }, + "document": { + "plainText": "sample", + "encrypted": { + "$binary": { + "base64": "A30AAAAQdAABAAAAEGEAAwAAAAVraQAQAAAABGFhYWFhYWFhYWFhYWFhYWEFa3UAEAAAAARhYWFhYWFhYWFhYWFhYWFhA3YAHgAAABB2AHsAAAAQbWluAAAAAAAQbWF4AMgAAAAAEmNtAAAAAAAAAAAAEnMAAQAAAAAAAAAA", + "subType": "06" + } + } + } + } + ], + "nsInfo": [ + { + "ns": "db.test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "equality", + "contention": { + "$numberLong": "0" + } + } + } + ] + } + } + } + } + ] + }, + "ok": { + "$numberDouble": "1.0" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/cmd-to-mongocryptd.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/cmd-to-mongocryptd.json new file mode 100644 index 0000000..46f8792 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/cmd-to-mongocryptd.json @@ -0,0 +1,30 @@ +{ + "bulkWrite": { + "$numberInt": "1" + }, + "ops": [ + { + "insert": 0, + "document": { + "plainText": "sample" + } + } + ], + "nsInfo": [ + { + "ns": "db.test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc", + "fields": [] + } + } + } + } + ] +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/cmd.json new file mode 100644 index 0000000..b7a53b5 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/cmd.json @@ -0,0 +1,17 @@ +{ + "bulkWrite": 1, + "ops": [ + { + "insert": 0, + "document": { + "plainText": "sample" + } + } + ], + "nsInfo": [ + { + "ns": "db.test" + } + ], + "$db": "admin" +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/mongocryptd-reply.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/mongocryptd-reply.json new file mode 100644 index 0000000..98ccba8 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/mongocryptd-reply.json @@ -0,0 +1,39 @@ +{ + "hasEncryptionPlaceholders": false, + "schemaRequiresEncryption": false, + "result": { + "bulkWrite": { + "$numberInt": "1" + }, + "ops": [ + { + "insert": { + "$numberInt": "0" + }, + "document": { + "plainText": "sample" + } + } + ], + "nsInfo": [ + { + "ns": "db.test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc", + "fields": [] + } + } + } + } + ] + }, + "ok": { + "$numberDouble": "1.0" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/payload.json b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/payload.json new file mode 100644 index 0000000..9c87c60 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/bulkWrite/unencrypted/payload.json @@ -0,0 +1,21 @@ +{ + "bulkWrite": { + "$numberInt": "1" + }, + "ops": [ + { + "insert": { + "$numberInt": "0" + }, + "document": { + "plainText": "sample" + } + } + ], + "$db": "admin", + "nsInfo": [ + { + "ns": "db.test" + } + ] +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/cleanup/missing-key-id/collinfo.json b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/missing-key-id/collinfo.json new file mode 100644 index 0000000..11bdd7d --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/missing-key-id/collinfo.json @@ -0,0 +1,20 @@ +{ + "options": { + "encryptedFields": { + "escCollection": "fle2.basic.esc", + "ecocCollection": "fle2.basic.ecoc", + "fields": [ + { + "path": "missingKeyId", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": { + "$numberLong": "0" + } + } + } + ] + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/cleanup/no-fields/collinfo.json b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/no-fields/collinfo.json new file mode 100644 index 0000000..9ba596c --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/no-fields/collinfo.json @@ -0,0 +1,9 @@ +{ + "options": { + "encryptedFields": { + "escCollection": "esc", + "ecocCollection": "ecoc", + "fields": [] + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/cleanup/no-fields/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/no-fields/encrypted-payload.json new file mode 100644 index 0000000..fc0daa7 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/no-fields/encrypted-payload.json @@ -0,0 +1,4 @@ +{ + "cleanupStructuredEncryptionData": "test", + "cleanupTokens": {} + } \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/cmd.json new file mode 100644 index 0000000..ec80fe9 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/cmd.json @@ -0,0 +1 @@ +{ "cleanupStructuredEncryptionData": "test" } diff --git a/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/collinfo.json b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/collinfo.json new file mode 100644 index 0000000..6a762e7 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/collinfo.json @@ -0,0 +1,63 @@ +{ + "options": { + "encryptedFields": { + "escCollection": "esc", + "ecocCollection": "ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "nested.encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "nested.notindexed", + "bsonType": "string" + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "rangeField", + "bsonType": "int", + "queries": { + "queryType": "range", + "contention": 0, + "sparsity": 1 + } + } + ] + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-field-config-map.json b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-field-config-map.json new file mode 100644 index 0000000..58ffe8f --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-field-config-map.json @@ -0,0 +1,61 @@ +{ + "db.test": { + "escCollection": "esc", + "ecocCollection": "ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "nested.encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "nested.notindexed", + "bsonType": "string" + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "rangeField", + "bsonType": "int", + "queries": { + "queryType": "range", + "contention": 0, + "sparsity": 1 + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-payload-range-v2.json b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-payload-range-v2.json new file mode 100644 index 0000000..1228b58 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-payload-range-v2.json @@ -0,0 +1,37 @@ +{ + "cleanupStructuredEncryptionData": "test", + "cleanupTokens": { + "rangeField": { + "ecoc": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "anchorPaddingToken": { + "$binary": { + "base64": "hjezd/cwUfInCg0WjvFlzdn9/BQa8upEyogsU5pMWMU=", + "subType": "00" + } + } + }, + "nested.notindexed": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "nested.encrypted": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "encrypted": { + "$binary": { + "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", + "subType": "00" + } + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-payload.json new file mode 100644 index 0000000..e2f16d3 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-payload.json @@ -0,0 +1,29 @@ +{ + "cleanupStructuredEncryptionData": "test", + "cleanupTokens": { + "rangeField": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "nested.notindexed": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "nested.encrypted": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "encrypted": { + "$binary": { + "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", + "subType": "00" + } + } + } +} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/cmd.json new file mode 100644 index 0000000..c9549fd --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/cmd.json @@ -0,0 +1 @@ +{ "compactStructuredEncryptionData": "test", "anchorPaddingFactor": 0.47 } diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/collinfo.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/collinfo.json new file mode 100644 index 0000000..9f06804 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/collinfo.json @@ -0,0 +1,64 @@ +{ + "options": { + "encryptedFields": { + "escCollection": "esc", + "eccCollection": "ecc", + "ecocCollection": "ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "nested.encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "nested.notindexed", + "bsonType": "string" + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "rangeField", + "bsonType": "int", + "queries": { + "queryType": "range", + "contention": 0, + "sparsity": 1 + } + } + ] + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/encrypted-payload-range-v2.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/encrypted-payload-range-v2.json new file mode 100644 index 0000000..8f3ba32 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/encrypted-payload-range-v2.json @@ -0,0 +1,105 @@ +{ + "compactStructuredEncryptionData": "test", + "anchorPaddingFactor": 0.47, + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "escCollection": "esc", + "eccCollection": "ecc", + "ecocCollection": "ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "nested.encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "nested.notindexed", + "bsonType": "string" + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "rangeField", + "bsonType": "int", + "queries": { + "queryType": "range", + "contention": 0, + "sparsity": 1 + } + } + ] + } + } + }, + "compactionTokens": { + "rangeField": { + "ecoc": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "anchorPaddingToken": { + "$binary": { + "base64": "hjezd/cwUfInCg0WjvFlzdn9/BQa8upEyogsU5pMWMU=", + "subType": "00" + } + } + }, + "nested.notindexed": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "nested.encrypted": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "encrypted": { + "$binary": { + "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", + "subType": "00" + } + } + } + } diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/encrypted-payload.json new file mode 100644 index 0000000..776dab3 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/anchor-pad/encrypted-payload.json @@ -0,0 +1,30 @@ +{ + "compactStructuredEncryptionData": "test", + "anchorPaddingFactor": 0.47, + "compactionTokens": { + "rangeField": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "nested.notindexed": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "nested.encrypted": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "encrypted": { + "$binary": { + "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", + "subType": "00" + } + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/cmd.json new file mode 100644 index 0000000..ddf4cfd --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/cmd.json @@ -0,0 +1 @@ +{ "compactStructuredEncryptionData": "test" } diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/collinfo.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/collinfo.json new file mode 100644 index 0000000..262768a --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/collinfo.json @@ -0,0 +1,49 @@ +{ + "options": { + "encryptedFields": { + "escCollection": "esc", + "eccCollection": "ecc", + "ecocCollection": "ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "nested.encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "nested.notindexed", + "bsonType": "string" + } + ] + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/encrypted-field-config-map.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/encrypted-field-config-map.json new file mode 100644 index 0000000..f183f7d --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/encrypted-field-config-map.json @@ -0,0 +1,47 @@ +{ + "db.test": { + "escCollection": "esc", + "eccCollection": "ecc", + "ecocCollection": "ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "nested.encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "nested.notindexed", + "bsonType": "string" + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/encrypted-payload.json new file mode 100644 index 0000000..f861ac7 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/no-range/encrypted-payload.json @@ -0,0 +1,23 @@ +{ + "compactStructuredEncryptionData": "test", + "compactionTokens": { + "nested.notindexed": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "nested.encrypted": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "encrypted": { + "$binary": { + "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", + "subType": "00" + } + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/success/collinfo.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/success/collinfo.json index 262768a..9f06804 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/compact/success/collinfo.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/success/collinfo.json @@ -42,6 +42,21 @@ }, "path": "nested.notindexed", "bsonType": "string" + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "rangeField", + "bsonType": "int", + "queries": { + "queryType": "range", + "contention": 0, + "sparsity": 1 + } } ] } diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-field-config-map.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-field-config-map.json index f183f7d..f61fe59 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-field-config-map.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-field-config-map.json @@ -41,6 +41,16 @@ }, "path": "nested.notindexed", "bsonType": "string" + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "rangeField", + "bsonType": "int" } ] } diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-payload-range-v2.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-payload-range-v2.json new file mode 100644 index 0000000..c3a677d --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-payload-range-v2.json @@ -0,0 +1,104 @@ +{ + "compactStructuredEncryptionData": "test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "escCollection": "esc", + "eccCollection": "ecc", + "ecocCollection": "ecoc", + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "nested.encrypted", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": 0 + } + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "nested.notindexed", + "bsonType": "string" + }, + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEw==", + "subType": "04" + } + }, + "path": "rangeField", + "bsonType": "int", + "queries": { + "queryType": "range", + "contention": 0, + "sparsity": 1 + } + } + ] + } + } + }, + "compactionTokens": { + "rangeField": { + "ecoc": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "anchorPaddingToken": { + "$binary": { + "base64": "hjezd/cwUfInCg0WjvFlzdn9/BQa8upEyogsU5pMWMU=", + "subType": "00" + } + } + }, + "nested.notindexed": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, + "nested.encrypted": { + "$binary": { + "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", + "subType": "00" + } + }, + "encrypted": { + "$binary": { + "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", + "subType": "00" + } + } + } + } diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-payload.json index c6dc271..7093253 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-payload.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-payload.json @@ -1,6 +1,12 @@ { "compactStructuredEncryptionData": "test", "compactionTokens": { + "rangeField": { + "$binary": { + "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", + "subType": "00" + } + }, "nested.notindexed": { "$binary": { "base64": "27J6DZqcjkRzZ3lWEsxH7CsQHr4CZirrGmuPS8ZkRO0=", diff --git a/ext/libmongocrypt/libmongocrypt/test/data/compact/success/mongocryptd-reply.json b/ext/libmongocrypt/libmongocrypt/test/data/compact/success/mongocryptd-reply.json deleted file mode 100644 index 2dbb796..0000000 --- a/ext/libmongocrypt/libmongocrypt/test/data/compact/success/mongocryptd-reply.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "ok": { - "$numberInt": "1" - }, - "result": { - "delete": "test", - "deletes": [ - { - "q": { - "value": { - "$binary": { - "base64": "A1gAAAAQdAACAAAAEGEAAgAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAASrze+rEjSYdhI0EjRWeJASEHYAQOIBABJjbQAAAAAAAAAAAAA=", - "subType": "06" - } - } - }, - "limit": 1 - } - ] - }, - "hasEncryptedPlaceholders": true, - "encryptionInformation": { - "type": 1, - "schema": { - "db.test": { - "escCollection": "esc", - "eccCollection": "ecc", - "ecocCollection": "ecoc", - "fields": [ - { - "keyId": { - "$binary": { - "base64": "EjRWeBI0mHYSNBI0VniQEg==", - "subType": "04" - } - }, - "path": "encrypted", - "bsonType": "string", - "queries": { - "queryType": "equality", - "contention": 0 - } - }, - { - "keyId": { - "$binary": { - "base64": "EjRWeBI0mHYSNBI0VniQEw==", - "subType": "04" - } - }, - "path": "nested.encrypted", - "bsonType": "string", - "queries": { - "queryType": "equality", - "contention": 0 - } - }, - { - "keyId": { - "$binary": { - "base64": "EjRWeBI0mHYSNBI0VniQFA==", - "subType": "04" - } - }, - "path": "nested.notindexed", - "bsonType": "string" - } - ] - } - } - } -} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/fle2-explain/with-csfle/collinfo.json b/ext/libmongocrypt/libmongocrypt/test/data/fle2-explain/with-csfle/collinfo.json index 928ccd1..539abcf 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/fle2-explain/with-csfle/collinfo.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/fle2-explain/with-csfle/collinfo.json @@ -1,9 +1,9 @@ { "options": { "encryptedFields": { - "escCollection": "esc", - "eccCollection": "ecc", - "ecocCollection": "ecoc", + "escCollection": "enxcol_.test.esc", + "eccCollection": "enxcol_.test.ecc", + "ecocCollection": "enxcol_.test.ecoc", "fields": [ { "keyId": { @@ -24,4 +24,4 @@ ] } } -} \ No newline at end of file +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/fle2-explain/with-csfle/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/fle2-explain/with-csfle/encrypted-payload.json index 31ed51e..9262d84 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/fle2-explain/with-csfle/encrypted-payload.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/fle2-explain/with-csfle/encrypted-payload.json @@ -17,9 +17,9 @@ }, "schema": { "db.test": { - "escCollection": "esc", - "eccCollection": "ecc", - "ecocCollection": "ecoc", + "escCollection": "enxcol_.test.esc", + "eccCollection": "enxcol_.test.ecc", + "ecocCollection": "enxcol_.test.ecoc", "fields": [ { "keyId": { diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/kms-decrypt-reply.txt b/ext/libmongocrypt/libmongocrypt/test/data/kms-aws/decrypt-response.txt similarity index 100% rename from ext/libmongocrypt/libmongocrypt/bindings/node/test/data/kms-decrypt-reply.txt rename to ext/libmongocrypt/libmongocrypt/test/data/kms-aws/decrypt-response.txt diff --git a/ext/libmongocrypt/libmongocrypt/bindings/node/test/data/kms-encrypt-reply.txt b/ext/libmongocrypt/libmongocrypt/test/data/kms-aws/encrypt-response.txt similarity index 100% rename from ext/libmongocrypt/libmongocrypt/bindings/node/test/data/kms-encrypt-reply.txt rename to ext/libmongocrypt/libmongocrypt/test/data/kms-aws/encrypt-response.txt diff --git a/ext/libmongocrypt/libmongocrypt/test/data/kms-azure/decrypt-response.txt b/ext/libmongocrypt/libmongocrypt/test/data/kms-azure/decrypt-response.txt new file mode 100644 index 0000000..bfe5691 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/kms-azure/decrypt-response.txt @@ -0,0 +1,16 @@ +HTTP/1.1 200 OK +Cache-Control: no-cache +Pragma: no-cache +Content-Type: application/json; charset=utf-8 +Expires: -1 +x-ms-keyvault-region: eastus +x-ms-request-id: 87ad5ae4-696a-46a4-87e0-cf13832a70ce +x-ms-keyvault-service-version: 1.9.1054.1 +x-ms-keyvault-network-info: conn_type=Ipv4;addr=98.110.73.14;act_addr_fam=InterNetwork; +X-Content-Type-Options: nosniff +Strict-Transport-Security: max-age=31536000;includeSubDomains +Date: Tue, 21 Nov 2023 13:41:26 GMT +Connection: close +Content-Length: 241 + +{"kid":"https://key-vault-csfle.vault.azure.net/keys/key-name-csfle/bf035425d3f44c51bb22244b7f58e350","value":"u3FgBLOThp0jDn3FqUPLnETuRNPYDCMET2F7gPkRHUNBrcc45ugX4sOB6Qx_p7TXO_PajifMQaFG5V3yH8hLz_vcMOJ1iSXQ5OZxf8aJ-YZQ2NJkZJofIBul97v6663Z"} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/data/kms-azure/encrypt-response.txt b/ext/libmongocrypt/libmongocrypt/test/data/kms-azure/encrypt-response.txt new file mode 100644 index 0000000..fc4e488 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/kms-azure/encrypt-response.txt @@ -0,0 +1,16 @@ +HTTP/1.1 200 OK +Cache-Control: no-cache +Pragma: no-cache +Content-Type: application/json; charset=utf-8 +Expires: -1 +x-ms-keyvault-region: eastus +x-ms-request-id: 180ebf78-d158-4349-bdc3-b6868fdcb7d0 +x-ms-keyvault-service-version: 1.9.1054.1 +x-ms-keyvault-network-info: conn_type=Ipv4;addr=98.110.73.14;act_addr_fam=InterNetwork; +X-Content-Type-Options: nosniff +Strict-Transport-Security: max-age=31536000;includeSubDomains +Date: Tue, 21 Nov 2023 13:35:21 GMT +Connection: close +Content-Length: 455 + +{"kid":"https://key-vault-csfle.vault.azure.net/keys/key-name-csfle/bf035425d3f44c51bb22244b7f58e350","value":"3hrs0cMlsmS7DDN2GNzR8n-CF59mzvrMTP3_dmBV1zzREob5muan2rYCcs7MU1k_ANZGaP4lWuDDVFuzwMTbhioFu64ypBDdMcKJ1VXMiKKNia1KgxJyDhDcc9Mq1fROvf5zXuceSBm1LjRenTMieBnFfO-V24cyDnj7KLdbdQHuf49RMHCWN7yq_vQ35Hobvzh1AO5WLB4MJUJLYh1r3BI2CNhMQT45L9Jkn_A4sTyKWfCpdVYgsi6XOv8bYSgM3fqhZnrtp2Q8cNY-_Nft08px8RGuLTLIzdrLyrtZ6dwpv7tWyamBJYxB4AQNKSiuKLxyvYLIxwQGasZrcfQqUQ"} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/data/kms-azure/oauth-response.txt b/ext/libmongocrypt/libmongocrypt/test/data/kms-azure/oauth-response.txt new file mode 100644 index 0000000..3ac9ece --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/kms-azure/oauth-response.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Cache-Control: no-store, no-cache +Pragma: no-cache +Content-Type: application/json; charset=utf-8 +Expires: -1 +Strict-Transport-Security: max-age=31536000; includeSubDomains +X-Content-Type-Options: nosniff +P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" +x-ms-request-id: 0f1342b1-6c07-45a7-8dfa-a5f90dc46b01 +x-ms-ests-server: 2.1.16729.8 - WUS3 ProdSlices +X-XSS-Protection: 0 +Set-Cookie: fpc=AvrLAj-gkztInBUWCCCIFDXJ8q5BAQAAABmp7twOAAAA; expires=Thu, 21-Dec-2023 13:35:21 GMT; path=/; secure; HttpOnly; SameSite=None +Set-Cookie: x-ms-gateway-slice=estsfd; path=/; secure; httponly +Set-Cookie: stsservicecookie=estsfd; path=/; secure; httponly +Date: Tue, 21 Nov 2023 13:35:21 GMT +Connection: close +Content-Length: 98 + +{"token_type":"Bearer","expires_in":3599,"ext_expires_in":3599,"access_token":"test-access-token"} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/data/gcp-auth/decrypt-response.txt b/ext/libmongocrypt/libmongocrypt/test/data/kms-gcp/decrypt-response.txt similarity index 100% rename from ext/libmongocrypt/libmongocrypt/test/data/gcp-auth/decrypt-response.txt rename to ext/libmongocrypt/libmongocrypt/test/data/kms-gcp/decrypt-response.txt diff --git a/ext/libmongocrypt/libmongocrypt/test/data/gcp-auth/encrypt-response.txt b/ext/libmongocrypt/libmongocrypt/test/data/kms-gcp/encrypt-response.txt similarity index 100% rename from ext/libmongocrypt/libmongocrypt/test/data/gcp-auth/encrypt-response.txt rename to ext/libmongocrypt/libmongocrypt/test/data/kms-gcp/encrypt-response.txt diff --git a/ext/libmongocrypt/libmongocrypt/test/data/gcp-auth/oauth-response.txt b/ext/libmongocrypt/libmongocrypt/test/data/kms-gcp/oauth-response.txt similarity index 100% rename from ext/libmongocrypt/libmongocrypt/test/data/gcp-auth/oauth-response.txt rename to ext/libmongocrypt/libmongocrypt/test/data/kms-gcp/oauth-response.txt diff --git a/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/cmd.json new file mode 100644 index 0000000..ce1686b --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/cmd.json @@ -0,0 +1,9 @@ +{ + "find": "test", + "filter": { + "plainText": "sample", + "encrypted": { + "$numberInt": "123456" + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/encrypted-field-map.json b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/encrypted-field-map.json new file mode 100644 index 0000000..e688460 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/encrypted-field-map.json @@ -0,0 +1,19 @@ +{ + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/encrypted-payload.json new file mode 100644 index 0000000..0dce092 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/encrypted-payload.json @@ -0,0 +1,62 @@ +{ + "find": "test", + "filter": { + "$and": [ + { + "plainText": { + "$eq": "sample" + } + }, + { + "$and": [ + { + "encrypted": { + "$gte": { + "$binary": { + "base64": "DQEBAAADcGF5bG9hZACZAAAABGcAhQAAAAMwAH0AAAAFZAAgAAAAABVoe9wkcCyHpbOGCU+k9auwnEcS2CtNpRqiecg98ONpBXMAIAAAAABvqHHsxgHdi12FXVttMVYYwNK4R2zYUjeXQHAURNBvzwVsACAAAAAAfmp4QWZF7LiYXH6RYjf1kc6OpgRnCadlHki6cRrMilsAABJjbQAIAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAASc3AAAQAAAAAAAAAQdGYABgAAABBtbgAAAACAEG14AP///38A", + "subType": "06" + } + } + } + }, + { + "encrypted": { + "$lte": { + "$binary": { + "base64": "DTsAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", + "subType": "06" + } + } + } + } + ] + } + ] + }, + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ], + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc" + } + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/mongocryptd-reply.json b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/mongocryptd-reply.json new file mode 100644 index 0000000..9c93298 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/find/mongocryptd-reply.json @@ -0,0 +1,69 @@ +{ + "hasEncryptionPlaceholders": true, + "schemaRequiresEncryption": true, + "result": { + "find": "test", + "filter": { + "$and": [ + { + "plainText": { + "$eq": "sample" + } + }, + { + "$and": [ + { + "encrypted": { + "$gte": { + "$binary": { + "base64": "AwABAAAQdAACAAAAEGEAAwAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAAQSNFZ4EjSYdhI0EjRWeJASA3YAoQAAAANlZGdlc0luZm8AWwAAABBsb3dlckJvdW5kAEDiAQAIbGJJbmNsdWRlZAABEHVwcGVyQm91bmQAQOIBAAh1YkluY2x1ZGVkAAEQaW5kZXhNaW4AAAAAgBBpbmRleE1heAD///9/ABBwYXlsb2FkSWQAAAAAABBmaXJzdE9wZXJhdG9yAAIAAAAQc2Vjb25kT3BlcmF0b3IABAAAAAASY20ACAAAAAAAAAAScwABAAAAAAAAAAA=", + "subType": "06" + } + } + } + }, + { + "encrypted": { + "$lte": { + "$binary": { + "base64": "A5oAAAAQdAACAAAAEGEAAwAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAAQSNFZ4EjSYdhI0EjRWeJASA3YAOwAAABBwYXlsb2FkSWQAAAAAABBmaXJzdE9wZXJhdG9yAAIAAAAQc2Vjb25kT3BlcmF0b3IABAAAAAASY20ACAAAAAAAAAAScwABAAAAAAAAAAA=", + "subType": "06" + } + } + } + } + ] + } + ] + }, + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ], + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc" + } + } + } + }, + "ok": { + "$numberDouble": "1.0" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/cmd.json new file mode 100644 index 0000000..938edd2 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/cmd.json @@ -0,0 +1,11 @@ +{ + "insert": "test", + "documents": [ + { + "plainText": "sample", + "encrypted": { + "$numberInt": "123456" + } + } + ] +} \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/encrypted-field-map.json b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/encrypted-field-map.json new file mode 100644 index 0000000..e688460 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/encrypted-field-map.json @@ -0,0 +1,19 @@ +{ + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/encrypted-payload.json new file mode 100644 index 0000000..722f052 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/encrypted-payload.json @@ -0,0 +1,40 @@ +{ + "insert": "test", + "documents": [ + { + "plainText": "sample", + "encrypted": { + "$binary": { + "base64": "CyAVAAAFZAAgAAAAAFX/OCQuK7sgFC5OgvIzRF0iZF5yZhqqgVEw+BDk04D/BXMAIAAAAADf8ZGTnPqqur9tusELGqTbSNtoJgj8i071DXm7kQpcSgVwADEAAAAAAwECAwECAwECAwECAwECAz+VM8kdZjiqXJ2Kga/NSZuITHP/iMRHFXZ17XdXy4FMWwV1ABAAAAAEEjRWeBI0mHYSNBI0VniQEhB0ABAAAAAFdgBQAAAAABI0VngSNJh2EjQSNFZ4kBIBAgMBAgMBAgMBAgMBAgMB978eymjOG8LzTgudRZqpbK4Tm1RK3tB9QMB9lTWKiy6Wqp7twzRA/ZbjQ69RKj60BWUAIAAAAADrmnP3kS2GpCl+gdL2da90KHTkBX46iQ/sZRoj7uPz7AVsACAAAAAAlO36MaVLVRDFW6xrI+0UTkyQdFfSCEBPkZg8sFzuTJYSawAGAAAAAAAAAARnAJkTAAADMAC2AAAABWQAIAAAAABx4c6MPMR3Yyxzi0dTMjQ7UdRNgI8uP2LTi1vhGYnLMAVzACAAAAAAon13gVyXE18K3ylqp/ovYStGulVBaekS2mKVRFq7RQgFbAAgAAAAAH5qeEFmRey4mFx+kWI39ZHOjqYEZwmnZR5IunEazIpbBXAAMQAAAAACAwECAwECAwECAwECAwECy273HayEz3hgoMYG56e0sxacPePKwPiqCCS575wlTLMxAAMxALYAAAAFZAAgAAAAALhKoC9+IzmWByMV7+lxHqBz30ckyd4wjXTJIaxvSHGQBXMAIAAAAADOFYCxSi5cl0dHBBpG2MuoCMK4VW7bnHkT4W0b8/S9QAVsACAAAAAA2ed4R4wYD6DT0P+N6o3gDJPE0DjljbRAv5vme3jb42sFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgMucSLry7LOh6S3NFriDyboyFWjjO7jUCKQmfnXNTVgRlsAAzIAtgAAAAVkACAAAAAA+QfEdnHiCdqN2uZKt8sulOoCI4Je4Lf2KfPWurcO6kcFcwAgAAAAAFvZ404SMykRwVDQtyApzVblLcZf0hl98cHQjbouG3VABWwAIAAAAAAYo/AvCQYlIUoNWV6sySJLiHk24w/YX3vRwwLVDjDsUgVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAele8PzNsBFG/0E0aRIa/STYmSf8Er7TW/aD841prevDywADMwC2AAAABWQAIAAAAADp37F20ZoHis9Y04z918sGyOCzOAnedki7o0xjs8aV4wVzACAAAAAA6gskIxd1RdPkI/t10Xs2RuQfNNaYAl0RCc/fEb9W590FbAAgAAAAAMf1cfJpJNlRk23xnpecqLu+IubHI7xMG6hGbCEA6QiiBXAAMQAAAAACAwECAwECAwECAwECAwECgxikv+dmmfSOXBQZkSatlNnFs2ATq0yp24nzunnI7mYwAAM0ALYAAAAFZAAgAAAAAG1JiCyGj5jLeMtQ0/UdOjg7P/gpwnYf6zlmRUnSU9tXBXMAIAAAAACtFe8XxEL7jbB4o17AIUTZ77heOzagFgk+Z2eL+QFeDQVsACAAAAAADYD3CyooN8IiEWsc1sPc1xCoRwH4F/+IYxDCubSkq+AFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgNNcU1NRd5pnVOIkx5k9qmZLy9F4raY2lK9H/NHP8CDC1sAAzUAtgAAAAVkACAAAAAAR3PxltBrzRZyAM57P9ciNMRpfyK+XB+QS0HJB/pFd3wFcwAgAAAAAEJoiSyFo2mxiXooeBm6E+rf3J90hTozFIFKSa5kPF1BBWwAIAAAAADmWysyKhf8UccKx78IliHTWao9pe/AwmLMDbMAnVJHPQVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAfDvmp5aIFHmt2vMpiuJI5jiaH7XRZ2dvrYZN5kjisPCywADNgC2AAAABWQAIAAAAACXnb80p8rHO1VZHz+NTqjUpoimkBybXrjMNLPk0Y2OUwVzACAAAAAAwRn8p8mm9fil7GXa4feiUPoaknS8X/eHqhu+Ynx2HEoFbAAgAAAAAAMUtyBHzqCfsTv4qaEnDPoB5Yb8qT4VjUppsq0/OY0mBXAAMQAAAAACAwECAwECAwECAwECAwECqAp8Ozm1Kd/Pk4q2oao5gsfAFcI39uY/eF2SybroFfEwAAM3ALYAAAAFZAAgAAAAAOW+ccgZnspe3Zk0B15sNoxYs+++vkIhLYDssUWrpf+ZBXMAIAAAAAC13nmuhE1cSoIdkJleu6iHCYZARpCxvagwSrdjvgaRUgVsACAAAAAAIrk7klUCamSAp05f9qK6PqR041yRVCaJ7dctpSUm5/gFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgNVutv0BdHOWmHtoNn6bEXHyRFbnxCJcfOzMiOveMdMVFsAAzgAtgAAAAVkACAAAAAAxbzcIam2ob0pklDpzLYr/BteO9cOCoJ0aWD6fGucXl0FcwAgAAAAAP5nX0Erewnh2CHdBDf3QsCG2XW2z90KD5B6Y+rzAl6ZBWwAIAAAAAAuKpEiz1IaNOIZ1+6lpo/M5wuUuwcW1GwgOCkqjExoOAVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAUzgTPP0+DG25jA52gXEcrK7bZQVD3qkpacpHd20tMAaywADOQC2AAAABWQAIAAAAAAcPMjPbOYfcAFEE0S3iUwoG9sWv8iy+fXbRTI5lfZ87QVzACAAAAAALfwKPHpI8mYj7xwh0i1P8MCp0LElos16pjLHMYy17gYFbAAgAAAAAHaai/vRhi3N4fiKYQomGNBSheDejcjnijIsVNmCu7vhBXAAMQAAAAACAwECAwECAwECAwECAwECRO+KoIpbLkFJkPNNknDUIv1zVweuC9zCdHTrmkor570wAAMxMAC2AAAABWQAIAAAAAAmoUbqGpreYSpgpkRV3PcLPwT90pv4J6Sq9hkzr1UyawVzACAAAAAAYK4KHqanlnpDmejdMXMo9/IdK47uVhuMyw1Lmg2S53gFbAAgAAAAAELpvtDOvYFsTO0EEkccCZpolG2C2oRSTimCz5l11QLTBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDgMqoRCc7BGqgadidlaTFtzKKMFdubtfXSHXfVstTOn5bAAMxMQC2AAAABWQAIAAAAAD0ugfk8nq6aFeln4+QLIhFyOkLafGcozN8MvybVLzaRgVzACAAAAAAC1ORUt0477aATkfBAN86Ky6TzUN4zYnGFdZw5VLJ3hcFbAAgAAAAAAs9x1SnVpMfNv5Bm1aXGwHmbbI9keWa9HRD35XuCBK5BXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBudSC4AK71+G+X6MfMuwKWRMnLOC4aidsIoUO0hV/QJTLAAMxMgC2AAAABWQAIAAAAADyKcEZ3l9iBRpFzfpofEfy1FkKktV1wzi2YMq438HAiQVzACAAAAAAJKWF4iNZdB6uI0t36zEsQpTi3cjhjMlUgJKxrQ5j19UFbAAgAAAAADj8Gb1dH1WJp8Z7W4Byzvjen38gy94jJ+bF4zcH8tB9BXAAMQAAAAACAwECAwECAwECAwECAwECTbYFftNKqDnEXKQbq2y3kKk4Wn5qJdjsUtSdBsj93m4wAAMxMwC2AAAABWQAIAAAAADQjZ9MCafSB+PIyoWl6zDRGcS/vGxSwQyuHHXESorF8AVzACAAAAAAMGC5dQYjHcHV9A+JDoOjcv7wEoZMiy6WCzo//5fJ7/EFbAAgAAAAAA8R9s/RrnxTOkU+fqYFsnAm0kmNKXhr0V3k/1OrtuTRBXAAMQAAAAADAQIDAQIDAQIDAQIDAQID0AQbL4e/j9E2BD/JqlROMj5nCV/Ms+LNiEKrM1EIMvdbAAMxNAC2AAAABWQAIAAAAADIgkDOvv4jRMk0e6Hw1NmMK/mrkkE68c74ahE/puHvbQVzACAAAAAA4CP/wdQvRwOl5t4mMgbwyhqjv01uiZveIj+U0dDmeJoFbAAgAAAAADpXRUP1KWfQopIEZgILyQjoq1rNc1SAgsP1U5QU0CREBXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBUqTscwusf1Sb9zr4ADXAuCcXXu6uLjV0FWzq5pdQ5hnLAAMxNQC2AAAABWQAIAAAAAClQOAmtdtHutim1zys0oMAxMkmClbHfAnkSLoTEjhwqwVzACAAAAAAVgt1FbCG6npznV3DHPsm1Zn2GJZMjjlE0wTUcCI0tOUFbAAgAAAAAArpkUe9A6CGOWFewttmaEMuVb6cJXc2tkP1R7vLf/SeBXAAMQAAAAACAwECAwECAwECAwECAwECPxj1iUCVNl0Z4rKvXKa9B6QsnyDHJyj8AUL42+SqvV4wAAMxNgC2AAAABWQAIAAAAACsc01M1lll1fAJc/LmqhR8KmQqlJ0ZGjHJ/Af0Jt3dzAVzACAAAAAAJ2n9ToriAiOreicCfmkRn3naQ7bIul0Xyjvnp6XTJbwFbAAgAAAAAKF92FNer/Q+vMlgRHGXnQP+EX9HQa2YYjTSon7O2IxDBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDxw1fFAt+kDNIihdC2r7837lNWG9IgpFMSUNza2MS+LpbAAMxNwC2AAAABWQAIAAAAACnNRIgrtUTrL9bvDzNfdzpGsdqBElHVWVpYyPXwSwrvgVzACAAAAAAjmBoFQHWGwST1BE0yaBiekIcYVsoUf/BSrLwO9UhtEsFbAAgAAAAAEe9aNvZUOhoa4IYjG0TUFY0Lbx6KYY//F0HqCDbN/u7BXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBPOd7p95VI1OtxfXq+5NSCH+ogPjo9lFrfeGODJKXKsjLAAMxOAC2AAAABWQAIAAAAAB69tLt+1PAUprgtKZWy3B9JL6GclTOi3dOgCCHgqPBnwVzACAAAAAAB8hNPjMyYRMHnH9XCVrcICu4ISWW3eCEUcSXZng35MAFbAAgAAAAAEcoyl5TBd6oEp+t0qD1tN0yjRtlGoa54w65U3dhexqRBXAAMQAAAAACAwECAwECAwECAwECAwECbtvNosMhvTRt45A7SQdH8hZippMddPE8g4K7zb6p7XswAAMxOQC2AAAABWQAIAAAAADO9uLhaBzFY2pp5k2huL0y7Ia9bbX9Td+8jbnze8vEoAVzACAAAAAAqE4YrbpDF0KstI1C6t+5gafrNKpWWc0gzHNa1VbxPjgFbAAgAAAAABkNIn+3njU/Zxu3Jz1yp3hxtx8KveIfzSQx6uLAsQLYBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDSCq69zvfhVJPRL0CTghUwWd8L3PWYQF7TwvOGZAw4z5bAAMyMAC2AAAABWQAIAAAAADUDjjIXc3gEKI0xh3UbzZvVMjQEJ3pHZDlee13ah248wVzACAAAAAAWfptH702DcaNwRMi0N3AN7Tr5qZhuecBsaFvVotkeOwFbAAgAAAAAO8B7P2R0zSBT5JbmwInpRsNZ2IJUMuL8l9VZjftP3WiBXAAMQAAAAABAgMBAgMBAgMBAgMBAgMB631+rWK1NZGz0Pf84u7wRYlfBwWhHkmrhvIRYczS5m/LAAMyMQC2AAAABWQAIAAAAABugPtcm/HV5MD8yyuw4bpcdO1+K8CkSbE/dhzK93fyJAVzACAAAAAAuKJP+IQVI2kYA02OeeHFQEmvuVVPFYtpD7nAcl4U8rYFbAAgAAAAAJRkWtjoKRlC5wNyXtyBUyPeH8hFa0fcZTw8R8alLt7QBXAAMQAAAAACAwECAwECAwECAwECAwEC0bHPZHQG/05yfKLiObxeknR1PuPEvJrR3f/s2ZiK+w0wAAMyMgC2AAAABWQAIAAAAAAtxq6iNLgn0d0g2oKCMOXZWf8LooZXa7CkhMlzX3U12gVzACAAAAAALUryeDpD1NktbkYTXUpsNQIJYr8I+fZBz4mFLSgtk44FbAAgAAAAAA9jJQaYWTOtI4mag6rZ7zycKpIHLEW0IkS8GCF5qSaMBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDzS5QIrvfRsnOnnZT+Z2BdcKeeWaIwToaTPER4e7sTohbAAMyMwC2AAAABWQAIAAAAAC6uNqCo6p+ohuqlioUo7bhj6L+0kJpFl3yLYfYhqbnrAVzACAAAAAAH6WDk481/wTTL/Y6t765GCYPH0niPXWzamTeZ6lEQkcFbAAgAAAAABhXLMOXrnco598ejjUHAkNGZR8eNVnDMWrAuQ16j2O/BXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBrSKQIVC2x1PtPhLkhY2Jahu7/uoimtsZXTegUO7y3MTLAAMyNAC2AAAABWQAIAAAAABkREAiEohu2Q1tDoksY567QbeolBSWlN9kY2VxQk2FnAVzACAAAAAAvDKcTZwlJBLt/1aRXy5ekX9Z/YcbhakokeaeY74zV4kFbAAgAAAAAEnd5ZUyXOLvEAhNT4ZKIDWE3wcv5mdo0crUrZauKMbnBXAAMQAAAAACAwECAwECAwECAwECAwEC1SEc0Ww2+DWHgLn9H3PFQ0KDejGQLLiQQ6CyyHitXjIwAAMyNQC2AAAABWQAIAAAAABn8GOJ0BUhqxsCMujadpEuMjQH/JqjdSe+d7ck4BJpBgVzACAAAAAA/+5+gxu0s/JHvMroY0hgg4/pNDl6+FbjkVVL4pp0wKAFbAAgAAAAAIZjTmkgXeFszdl7b+WoFTth6LSUyRYvg6eh5JiOaoBYBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDH4rc2ZooIeKkTPqox5+Nw09+L+D6wJq4Ei3fLly1HaZbAAMyNgC2AAAABWQAIAAAAAA+kw8ODbANBx/7vTQYS+vKeqcxI7s64zzuGVo9ISg+EAVzACAAAAAAijiBsW795UOqu7fNmYqbj7uSBToUCGU/mdufHc5RCl0FbAAgAAAAAFIO6h0rFmqi1XsueSDzF02jzB81vUi+aMj/LuTEHIdqBXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBOL+SA7F+3RSUqlMTq7mr/YYm5JnUr8uVrojhKonnlN7LAAASc3AAAQAAAAAAAAAQdGYABgAAABBtbgAAAACAEG14AP///38A", + "subType": "06" + } + } + } + ], + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ], + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc" + } + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/mongocryptd-reply.json b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/mongocryptd-reply.json new file mode 100644 index 0000000..bc4e269 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/no-trimFactor/insert/mongocryptd-reply.json @@ -0,0 +1,47 @@ +{ + "hasEncryptionPlaceholders": true, + "schemaRequiresEncryption": true, + "result": { + "insert": "test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ], + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc" + } + } + }, + "documents": [ + { + "plainText": "sample", + "encrypted": { + "$binary": { + "base64": "A30AAAAQdAABAAAAEGEAAwAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAAQSNFZ4EjSYdhI0EjRWeJASA3YAHgAAABB2AEDiAQAQbWluAAAAAIAQbWF4AP///38AEmNtAAgAAAAAAAAAEnMAAQAAAAAAAAAA", + "subType": "06" + } + } + } + ] + }, + "ok": { + "$numberDouble": "1.0" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_decimal128.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_decimal128.cstruct index e2f5a98..5741c36 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_decimal128.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_decimal128.cstruct @@ -1,4 +1,4 @@ -// This code is GENERATED! Do not edit! +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` // clang-format off { .value = MC_DEC128(0), diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_double.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_double.cstruct index 81d1053..ce49ecb 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_double.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_double.cstruct @@ -1,7959 +1,8638 @@ -// This is a copy of test vectors from the mongodb/mongo repository. -// The order of edges is rearranged to permit exact matching. - -{ - .value = 0.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000000", - "1000000000000", - "10000000000000", - "100000000000000", - "1000000000000000", - "10000000000000000", - "100000000000000000", - "1000000000000000000", - "10000000000000000000", - "100000000000000000000", - "1000000000000000000000", - "10000000000000000000000", - "100000000000000000000000", - "1000000000000000000000000", - "10000000000000000000000000", - "100000000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000", - "1000000000000000000000000000000000", - "10000000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000000", - "10000000000000", - "1000000000000000", - "100000000000000000", - "10000000000000000000", - "1000000000000000000000", - "100000000000000000000000", - "10000000000000000000000000", - "1000000000000000000000000000", - "100000000000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000", - "100000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000000", - "100000000000000", - "100000000000000000", - "100000000000000000000", - "100000000000000000000000", - "100000000000000000000000000", - "100000000000000000000000000000", - "100000000000000000000000000000000", - "100000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000000", - "1000000000000000", - "10000000000000000000", - "100000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000000000", - "100000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000000000000000", - "100000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000000", - "1000000000000", - "10000000000000", - "100000000000000", - "1000000000000000", - "10000000000000000", - "100000000000000000", - "1000000000000000000", - "10000000000000000000", - "100000000000000000000", - "1000000000000000000000", - "10000000000000000000000", - "100000000000000000000000", - "1000000000000000000000000", - "10000000000000000000000000", - "100000000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000", - "1000000000000000000000000000000000", - "10000000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000000", - "10000000000000", - "1000000000000000", - "100000000000000000", - "10000000000000000000", - "1000000000000000000000", - "100000000000000000000000", - "10000000000000000000000000", - "1000000000000000000000000000", - "100000000000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000", - "100000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000000", - "100000000000000", - "100000000000000000", - "100000000000000000000", - "100000000000000000000000", - "100000000000000000000000000", - "100000000000000000000000000000", - "100000000000000000000000000000000", - "100000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000000", - "1000000000000000", - "10000000000000000000", - "100000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000000000", - "100000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000000000000000", - "100000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000000", - "1000000000000", - "10000000000000", - "100000000000000", - "1000000000000000", - "10000000000000000", - "100000000000000000", - "1000000000000000000", - "10000000000000000000", - "100000000000000000000", - "1000000000000000000000", - "10000000000000000000000", - "100000000000000000000000", - "1000000000000000000000000", - "10000000000000000000000000", - "100000000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000", - "1000000000000000000000000000000000", - "10000000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000000", - "10000000000000", - "1000000000000000", - "100000000000000000", - "10000000000000000000", - "1000000000000000000000", - "100000000000000000000000", - "10000000000000000000000000", - "1000000000000000000000000000", - "100000000000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000", - "100000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000000", - "100000000000000", - "100000000000000000", - "100000000000000000000", - "100000000000000000000000", - "100000000000000000000000000", - "100000000000000000000000000000", - "100000000000000000000000000000000", - "100000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000000", - "1000000000000000", - "10000000000000000000", - "100000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000000000", - "100000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000000000000000", - "100000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000000", - "1000000000000", - "10000000000000", - "100000000000000", - "1000000000000000", - "10000000000000000", - "100000000000000000", - "1000000000000000000", - "10000000000000000000", - "100000000000000000000", - "1000000000000000000000", - "10000000000000000000000", - "100000000000000000000000", - "1000000000000000000000000", - "10000000000000000000000000", - "100000000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000", - "1000000000000000000000000000000000", - "10000000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000000", - "10000000000000", - "1000000000000000", - "100000000000000000", - "10000000000000000000", - "1000000000000000000000", - "100000000000000000000000", - "10000000000000000000000000", - "1000000000000000000000000000", - "100000000000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000", - "100000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000000", - "100000000000000", - "100000000000000000", - "100000000000000000000", - "100000000000000000000000", - "100000000000000000000000000", - "100000000000000000000000000000", - "100000000000000000000000000000000", - "100000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000000", - "1000000000000000", - "10000000000000000000", - "100000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000000000", - "100000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000000000000000", - "100000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000000", - "1000000000000", - "10000000000000", - "100000000000000", - "1000000000000000", - "10000000000000000", - "100000000000000000", - "1000000000000000000", - "10000000000000000000", - "100000000000000000000", - "1000000000000000000000", - "10000000000000000000000", - "100000000000000000000000", - "1000000000000000000000000", - "10000000000000000000000000", - "100000000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000", - "1000000000000000000000000000000000", - "10000000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000000", - "10000000000000", - "1000000000000000", - "100000000000000000", - "10000000000000000000", - "1000000000000000000000", - "100000000000000000000000", - "10000000000000000000000000", - "1000000000000000000000000000", - "100000000000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000", - "100000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000000", - "100000000000000", - "100000000000000000", - "100000000000000000000", - "100000000000000000000000", - "100000000000000000000000000", - "100000000000000000000000000000", - "100000000000000000000000000000000", - "100000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000000", - "1000000000000000", - "10000000000000000000", - "100000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000000000", - "100000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000000000000000", - "100000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000000", - "1000000000000", - "10000000000000", - "100000000000000", - "1000000000000000", - "10000000000000000", - "100000000000000000", - "1000000000000000000", - "10000000000000000000", - "100000000000000000000", - "1000000000000000000000", - "10000000000000000000000", - "100000000000000000000000", - "1000000000000000000000000", - "10000000000000000000000000", - "100000000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000", - "1000000000000000000000000000000000", - "10000000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000000", - "10000000000000", - "1000000000000000", - "100000000000000000", - "10000000000000000000", - "1000000000000000000000", - "100000000000000000000000", - "10000000000000000000000000", - "1000000000000000000000000000", - "100000000000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000", - "100000000000000000000000000000000000", - "10000000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000000", - "100000000000000", - "100000000000000000", - "100000000000000000000", - "100000000000000000000000", - "100000000000000000000000000", - "100000000000000000000000000000", - "100000000000000000000000000000000", - "100000000000000000000000000000000000", - "100000000000000000000000000000000000000", - "100000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000000", - "1000000000000000", - "10000000000000000000", - "100000000000000000000000", - "1000000000000000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000000000", - "100000000000000000000000", - "10000000000000000000000000000000", - "1000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000000000000", - "100000000000000000000000000000", - "1000000000000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000", - "100000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000000000000000", - "100000000000000000000000000000000", - "10000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000", - "10000000000000000000000000000000", - "100000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000", - "10000000000000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = 0.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000000000000000000000000000000000000000000000000000000000", - "10000000000000000000000000000000" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0", - "01", - "010", - "0100", - "01000", - "010000", - "0100000", - "01000000", - "010000001", - "0100000010", - "01000000100", - "010000001000", - "0100000010000", - "01000000100000", - "010000001000001", - "0100000010000011", - "01000000100000110", - "010000001000001101", - "0100000010000011010", - "01000000100000110101", - "010000001000001101010", - "0100000010000011010100", - "01000000100000110101001", - "010000001000001101010011", - "0100000010000011010100111", - "01000000100000110101001111", - "010000001000001101010011111", - "0100000010000011010100111111", - "01000000100000110101001111110", - "010000001000001101010011111101", - "0100000010000011010100111111011", - "01000000100000110101001111110111", - "010000001000001101010011111101111", - "0100000010000011010100111111011111", - "01000000100000110101001111110111110", - "010000001000001101010011111101111100", - "0100000010000011010100111111011111001", - "01000000100000110101001111110111110011", - "010000001000001101010011111101111100111", - "0100000010000011010100111111011111001110", - "01000000100000110101001111110111110011101", - "010000001000001101010011111101111100111011", - "0100000010000011010100111111011111001110110", - "01000000100000110101001111110111110011101101", - "010000001000001101010011111101111100111011011", - "0100000010000011010100111111011111001110110110", - "01000000100000110101001111110111110011101101100", - "010000001000001101010011111101111100111011011001", - "0100000010000011010100111111011111001110110110010", - "01000000100000110101001111110111110011101101100100", - "010000001000001101010011111101111100111011011001000", - "0100000010000011010100111111011111001110110110010001", - "01000000100000110101001111110111110011101101100100010", - "010000001000001101010011111101111100111011011001000101", - "0100000010000011010100111111011111001110110110010001011", - "01000000100000110101001111110111110011101101100100010110", - "010000001000001101010011111101111100111011011001000101101", - "0100000010000011010100111111011111001110110110010001011010", - "01000000100000110101001111110111110011101101100100010110100", - "010000001000001101010011111101111100111011011001000101101000", - "0100000010000011010100111111011111001110110110010001011010000", - "01000000100000110101001111110111110011101101100100010110100001", - "010000001000001101010011111101111100111011011001000101101000011" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01", - "0100", - "010000", - "01000000", - "0100000010", - "010000001000", - "01000000100000", - "0100000010000011", - "010000001000001101", - "01000000100000110101", - "0100000010000011010100", - "010000001000001101010011", - "01000000100000110101001111", - "0100000010000011010100111111", - "010000001000001101010011111101", - "01000000100000110101001111110111", - "0100000010000011010100111111011111", - "010000001000001101010011111101111100", - "01000000100000110101001111110111110011", - "0100000010000011010100111111011111001110", - "010000001000001101010011111101111100111011", - "01000000100000110101001111110111110011101101", - "0100000010000011010100111111011111001110110110", - "010000001000001101010011111101111100111011011001", - "01000000100000110101001111110111110011101101100100", - "0100000010000011010100111111011111001110110110010001", - "010000001000001101010011111101111100111011011001000101", - "01000000100000110101001111110111110011101101100100010110", - "0100000010000011010100111111011111001110110110010001011010", - "010000001000001101010011111101111100111011011001000101101000", - "01000000100000110101001111110111110011101101100100010110100001" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "010", - "010000", - "010000001", - "010000001000", - "010000001000001", - "010000001000001101", - "010000001000001101010", - "010000001000001101010011", - "010000001000001101010011111", - "010000001000001101010011111101", - "010000001000001101010011111101111", - "010000001000001101010011111101111100", - "010000001000001101010011111101111100111", - "010000001000001101010011111101111100111011", - "010000001000001101010011111101111100111011011", - "010000001000001101010011111101111100111011011001", - "010000001000001101010011111101111100111011011001000", - "010000001000001101010011111101111100111011011001000101", - "010000001000001101010011111101111100111011011001000101101", - "010000001000001101010011111101111100111011011001000101101000", - "010000001000001101010011111101111100111011011001000101101000011" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100", - "01000000", - "010000001000", - "0100000010000011", - "01000000100000110101", - "010000001000001101010011", - "0100000010000011010100111111", - "01000000100000110101001111110111", - "010000001000001101010011111101111100", - "0100000010000011010100111111011111001110", - "01000000100000110101001111110111110011101101", - "010000001000001101010011111101111100111011011001", - "0100000010000011010100111111011111001110110110010001", - "01000000100000110101001111110111110011101101100100010110", - "010000001000001101010011111101111100111011011001000101101000" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01000000", - "0100000010000011", - "010000001000001101010011", - "01000000100000110101001111110111", - "0100000010000011010100111111011111001110", - "010000001000001101010011111101111100111011011001", - "01000000100000110101001111110111110011101101100100010110" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100000010", - "01000000100000110101", - "010000001000001101010011111101", - "0100000010000011010100111111011111001110", - "01000000100000110101001111110111110011101101100100", - "010000001000001101010011111101111100111011011001000101101000" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01000000100", - "0100000010000011010100", - "010000001000001101010011111101111", - "01000000100000110101001111110111110011101101", - "0100000010000011010100111111011111001110110110010001011" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100000010000011", - "01000000100000110101001111110111", - "010000001000001101010011111101111100111011011001" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100000010000011010100111111011", - "01000000100000110101001111110111110011101101100100010110100001" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01000000100000110101001111110111" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0", - "01", - "010", - "0100", - "01000", - "010000", - "0100000", - "01000000", - "010000001", - "0100000010", - "01000000100", - "010000001000", - "0100000010000", - "01000000100000", - "010000001000001", - "0100000010000011", - "01000000100000110", - "010000001000001101", - "0100000010000011010", - "01000000100000110101", - "010000001000001101010", - "0100000010000011010100", - "01000000100000110101001", - "010000001000001101010011", - "0100000010000011010100111", - "01000000100000110101001111", - "010000001000001101010011111", - "0100000010000011010100111111", - "01000000100000110101001111110", - "010000001000001101010011111101", - "0100000010000011010100111111011", - "01000000100000110101001111110111", - "010000001000001101010011111101111", - "0100000010000011010100111111011111", - "01000000100000110101001111110111110", - "010000001000001101010011111101111100", - "0100000010000011010100111111011111001", - "01000000100000110101001111110111110011", - "010000001000001101010011111101111100111", - "0100000010000011010100111111011111001110", - "01000000100000110101001111110111110011101", - "010000001000001101010011111101111100111011", - "0100000010000011010100111111011111001110110", - "01000000100000110101001111110111110011101101", - "010000001000001101010011111101111100111011011", - "0100000010000011010100111111011111001110110110", - "01000000100000110101001111110111110011101101100", - "010000001000001101010011111101111100111011011001", - "0100000010000011010100111111011111001110110110010", - "01000000100000110101001111110111110011101101100100", - "010000001000001101010011111101111100111011011001000", - "0100000010000011010100111111011111001110110110010001", - "01000000100000110101001111110111110011101101100100010", - "010000001000001101010011111101111100111011011001000101", - "0100000010000011010100111111011111001110110110010001011", - "01000000100000110101001111110111110011101101100100010110", - "010000001000001101010011111101111100111011011001000101101", - "0100000010000011010100111111011111001110110110010001011010", - "01000000100000110101001111110111110011101101100100010110100", - "010000001000001101010011111101111100111011011001000101101000", - "0100000010000011010100111111011111001110110110010001011010000", - "01000000100000110101001111110111110011101101100100010110100001", - "010000001000001101010011111101111100111011011001000101101000011" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01", - "0100", - "010000", - "01000000", - "0100000010", - "010000001000", - "01000000100000", - "0100000010000011", - "010000001000001101", - "01000000100000110101", - "0100000010000011010100", - "010000001000001101010011", - "01000000100000110101001111", - "0100000010000011010100111111", - "010000001000001101010011111101", - "01000000100000110101001111110111", - "0100000010000011010100111111011111", - "010000001000001101010011111101111100", - "01000000100000110101001111110111110011", - "0100000010000011010100111111011111001110", - "010000001000001101010011111101111100111011", - "01000000100000110101001111110111110011101101", - "0100000010000011010100111111011111001110110110", - "010000001000001101010011111101111100111011011001", - "01000000100000110101001111110111110011101101100100", - "0100000010000011010100111111011111001110110110010001", - "010000001000001101010011111101111100111011011001000101", - "01000000100000110101001111110111110011101101100100010110", - "0100000010000011010100111111011111001110110110010001011010", - "010000001000001101010011111101111100111011011001000101101000", - "01000000100000110101001111110111110011101101100100010110100001" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "010", - "010000", - "010000001", - "010000001000", - "010000001000001", - "010000001000001101", - "010000001000001101010", - "010000001000001101010011", - "010000001000001101010011111", - "010000001000001101010011111101", - "010000001000001101010011111101111", - "010000001000001101010011111101111100", - "010000001000001101010011111101111100111", - "010000001000001101010011111101111100111011", - "010000001000001101010011111101111100111011011", - "010000001000001101010011111101111100111011011001", - "010000001000001101010011111101111100111011011001000", - "010000001000001101010011111101111100111011011001000101", - "010000001000001101010011111101111100111011011001000101101", - "010000001000001101010011111101111100111011011001000101101000", - "010000001000001101010011111101111100111011011001000101101000011" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100", - "01000000", - "010000001000", - "0100000010000011", - "01000000100000110101", - "010000001000001101010011", - "0100000010000011010100111111", - "01000000100000110101001111110111", - "010000001000001101010011111101111100", - "0100000010000011010100111111011111001110", - "01000000100000110101001111110111110011101101", - "010000001000001101010011111101111100111011011001", - "0100000010000011010100111111011111001110110110010001", - "01000000100000110101001111110111110011101101100100010110", - "010000001000001101010011111101111100111011011001000101101000" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01000000", - "0100000010000011", - "010000001000001101010011", - "01000000100000110101001111110111", - "0100000010000011010100111111011111001110", - "010000001000001101010011111101111100111011011001", - "01000000100000110101001111110111110011101101100100010110" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100000010", - "01000000100000110101", - "010000001000001101010011111101", - "0100000010000011010100111111011111001110", - "01000000100000110101001111110111110011101101100100", - "010000001000001101010011111101111100111011011001000101101000" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01000000100", - "0100000010000011010100", - "010000001000001101010011111101111", - "01000000100000110101001111110111110011101101", - "0100000010000011010100111111011111001110110110010001011" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100000010000011", - "01000000100000110101001111110111", - "010000001000001101010011111101111100111011011001" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100000010000011010100111111011", - "01000000100000110101001111110111110011101101100100010110100001" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01000000100000110101001111110111" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0", - "01", - "010", - "0100", - "01000", - "010000", - "0100000", - "01000000", - "010000001", - "0100000010", - "01000000100", - "010000001000", - "0100000010000", - "01000000100000", - "010000001000001", - "0100000010000011", - "01000000100000110", - "010000001000001101", - "0100000010000011010", - "01000000100000110101", - "010000001000001101010", - "0100000010000011010100", - "01000000100000110101001", - "010000001000001101010011", - "0100000010000011010100111", - "01000000100000110101001111", - "010000001000001101010011111", - "0100000010000011010100111111", - "01000000100000110101001111110", - "010000001000001101010011111101", - "0100000010000011010100111111011", - "01000000100000110101001111110111", - "010000001000001101010011111101111", - "0100000010000011010100111111011111", - "01000000100000110101001111110111110", - "010000001000001101010011111101111100", - "0100000010000011010100111111011111001", - "01000000100000110101001111110111110011", - "010000001000001101010011111101111100111", - "0100000010000011010100111111011111001110", - "01000000100000110101001111110111110011101", - "010000001000001101010011111101111100111011", - "0100000010000011010100111111011111001110110", - "01000000100000110101001111110111110011101101", - "010000001000001101010011111101111100111011011", - "0100000010000011010100111111011111001110110110", - "01000000100000110101001111110111110011101101100", - "010000001000001101010011111101111100111011011001", - "0100000010000011010100111111011111001110110110010", - "01000000100000110101001111110111110011101101100100", - "010000001000001101010011111101111100111011011001000", - "0100000010000011010100111111011111001110110110010001", - "01000000100000110101001111110111110011101101100100010", - "010000001000001101010011111101111100111011011001000101", - "0100000010000011010100111111011111001110110110010001011", - "01000000100000110101001111110111110011101101100100010110", - "010000001000001101010011111101111100111011011001000101101", - "0100000010000011010100111111011111001110110110010001011010", - "01000000100000110101001111110111110011101101100100010110100", - "010000001000001101010011111101111100111011011001000101101000", - "0100000010000011010100111111011111001110110110010001011010000", - "01000000100000110101001111110111110011101101100100010110100001", - "010000001000001101010011111101111100111011011001000101101000011" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01", - "0100", - "010000", - "01000000", - "0100000010", - "010000001000", - "01000000100000", - "0100000010000011", - "010000001000001101", - "01000000100000110101", - "0100000010000011010100", - "010000001000001101010011", - "01000000100000110101001111", - "0100000010000011010100111111", - "010000001000001101010011111101", - "01000000100000110101001111110111", - "0100000010000011010100111111011111", - "010000001000001101010011111101111100", - "01000000100000110101001111110111110011", - "0100000010000011010100111111011111001110", - "010000001000001101010011111101111100111011", - "01000000100000110101001111110111110011101101", - "0100000010000011010100111111011111001110110110", - "010000001000001101010011111101111100111011011001", - "01000000100000110101001111110111110011101101100100", - "0100000010000011010100111111011111001110110110010001", - "010000001000001101010011111101111100111011011001000101", - "01000000100000110101001111110111110011101101100100010110", - "0100000010000011010100111111011111001110110110010001011010", - "010000001000001101010011111101111100111011011001000101101000", - "01000000100000110101001111110111110011101101100100010110100001" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "010", - "010000", - "010000001", - "010000001000", - "010000001000001", - "010000001000001101", - "010000001000001101010", - "010000001000001101010011", - "010000001000001101010011111", - "010000001000001101010011111101", - "010000001000001101010011111101111", - "010000001000001101010011111101111100", - "010000001000001101010011111101111100111", - "010000001000001101010011111101111100111011", - "010000001000001101010011111101111100111011011", - "010000001000001101010011111101111100111011011001", - "010000001000001101010011111101111100111011011001000", - "010000001000001101010011111101111100111011011001000101", - "010000001000001101010011111101111100111011011001000101101", - "010000001000001101010011111101111100111011011001000101101000", - "010000001000001101010011111101111100111011011001000101101000011" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100", - "01000000", - "010000001000", - "0100000010000011", - "01000000100000110101", - "010000001000001101010011", - "0100000010000011010100111111", - "01000000100000110101001111110111", - "010000001000001101010011111101111100", - "0100000010000011010100111111011111001110", - "01000000100000110101001111110111110011101101", - "010000001000001101010011111101111100111011011001", - "0100000010000011010100111111011111001110110110010001", - "01000000100000110101001111110111110011101101100100010110", - "010000001000001101010011111101111100111011011001000101101000" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01000000", - "0100000010000011", - "010000001000001101010011", - "01000000100000110101001111110111", - "0100000010000011010100111111011111001110", - "010000001000001101010011111101111100111011011001", - "01000000100000110101001111110111110011101101100100010110" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100000010", - "01000000100000110101", - "010000001000001101010011111101", - "0100000010000011010100111111011111001110", - "01000000100000110101001111110111110011101101100100", - "010000001000001101010011111101111100111011011001000101101000" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01000000100", - "0100000010000011010100", - "010000001000001101010011111101111", - "01000000100000110101001111110111110011101101", - "0100000010000011010100111111011111001110110110010001011" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100000010000011", - "01000000100000110101001111110111", - "010000001000001101010011111101111100111011011001" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "0100000010000011010100111111011", - "01000000100000110101001111110111110011101101100100010110100001" - } -}, -{ - .value = -0.00700000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "0100000010000011010100111111011111001110110110010001011010000111", - "01000000100000110101001111110111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 1, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1", - "11", - "110", - "1100", - "11000", - "110000", - "1100000", - "11000000", - "110000000", - "1100000001", - "11000000010", - "110000000100", - "1100000001000", - "11000000010000", - "110000000100000", - "1100000001000000", - "11000000010000000", - "110000000100000001", - "1100000001000000011", - "11000000010000000110", - "110000000100000001100", - "1100000001000000011000", - "11000000010000000110001", - "110000000100000001100011", - "1100000001000000011000110", - "11000000010000000110001101", - "110000000100000001100011011", - "1100000001000000011000110111", - "11000000010000000110001101110", - "110000000100000001100011011101", - "1100000001000000011000110111010", - "11000000010000000110001101110100", - "110000000100000001100011011101001", - "1100000001000000011000110111010010", - "11000000010000000110001101110100101", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111", - "11000000010000000110001101110100101111", - "110000000100000001100011011101001011110", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000", - "110000000100000001100011011101001011110001", - "1100000001000000011000110111010010111100011", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101", - "1100000001000000011000110111010010111100011010", - "11000000010000000110001101110100101111000110101", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111", - "110000000100000001100011011101001011110001101010011111", - "1100000001000000011000110111010010111100011010100111111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101", - "1100000001000000011000110111010010111100011010100111111011", - "11000000010000000110001101110100101111000110101001111110111", - "110000000100000001100011011101001011110001101010011111101111", - "1100000001000000011000110111010010111100011010100111111011111", - "11000000010000000110001101110100101111000110101001111110111110", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 2, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11", - "1100", - "110000", - "11000000", - "1100000001", - "110000000100", - "11000000010000", - "1100000001000000", - "110000000100000001", - "11000000010000000110", - "1100000001000000011000", - "110000000100000001100011", - "11000000010000000110001101", - "1100000001000000011000110111", - "110000000100000001100011011101", - "11000000010000000110001101110100", - "1100000001000000011000110111010010", - "110000000100000001100011011101001011", - "11000000010000000110001101110100101111", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001", - "1100000001000000011000110111010010111100011010100111", - "110000000100000001100011011101001011110001101010011111", - "11000000010000000110001101110100101111000110101001111110", - "1100000001000000011000110111010010111100011010100111111011", - "110000000100000001100011011101001011110001101010011111101111", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 3, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "110", - "110000", - "110000000", - "110000000100", - "110000000100000", - "110000000100000001", - "110000000100000001100", - "110000000100000001100011", - "110000000100000001100011011", - "110000000100000001100011011101", - "110000000100000001100011011101001", - "110000000100000001100011011101001011", - "110000000100000001100011011101001011110", - "110000000100000001100011011101001011110001", - "110000000100000001100011011101001011110001101", - "110000000100000001100011011101001011110001101010", - "110000000100000001100011011101001011110001101010011", - "110000000100000001100011011101001011110001101010011111", - "110000000100000001100011011101001011110001101010011111101", - "110000000100000001100011011101001011110001101010011111101111", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 4, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100", - "11000000", - "110000000100", - "1100000001000000", - "11000000010000000110", - "110000000100000001100011", - "1100000001000000011000110111", - "11000000010000000110001101110100", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 8, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000", - "1100000001000000", - "110000000100000001100011", - "11000000010000000110001101110100", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 10, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001", - "11000000010000000110", - "110000000100000001100011011101", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 11, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010", - "1100000001000000011000", - "110000000100000001100011011101001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010100111111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 16, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000", - "11000000010000000110001101110100", - "110000000100000001100011011101001011110001101010" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 31, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000011000110111010", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 32, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010000000110001101110100" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 1, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1", - "11", - "110", - "1100", - "11000", - "110000", - "1100000", - "11000000", - "110000000", - "1100000001", - "11000000010", - "110000000100", - "1100000001000", - "11000000010000", - "110000000100000", - "1100000001000000", - "11000000010000000", - "110000000100000001", - "1100000001000000011", - "11000000010000000110", - "110000000100000001100", - "1100000001000000011000", - "11000000010000000110001", - "110000000100000001100011", - "1100000001000000011000110", - "11000000010000000110001101", - "110000000100000001100011011", - "1100000001000000011000110111", - "11000000010000000110001101110", - "110000000100000001100011011101", - "1100000001000000011000110111010", - "11000000010000000110001101110100", - "110000000100000001100011011101001", - "1100000001000000011000110111010010", - "11000000010000000110001101110100101", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111", - "11000000010000000110001101110100101111", - "110000000100000001100011011101001011110", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000", - "110000000100000001100011011101001011110001", - "1100000001000000011000110111010010111100011", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101", - "1100000001000000011000110111010010111100011010", - "11000000010000000110001101110100101111000110101", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111", - "110000000100000001100011011101001011110001101010011111", - "1100000001000000011000110111010010111100011010100111111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101", - "1100000001000000011000110111010010111100011010100111111011", - "11000000010000000110001101110100101111000110101001111110111", - "110000000100000001100011011101001011110001101010011111101111", - "1100000001000000011000110111010010111100011010100111111011111", - "11000000010000000110001101110100101111000110101001111110111110", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 2, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11", - "1100", - "110000", - "11000000", - "1100000001", - "110000000100", - "11000000010000", - "1100000001000000", - "110000000100000001", - "11000000010000000110", - "1100000001000000011000", - "110000000100000001100011", - "11000000010000000110001101", - "1100000001000000011000110111", - "110000000100000001100011011101", - "11000000010000000110001101110100", - "1100000001000000011000110111010010", - "110000000100000001100011011101001011", - "11000000010000000110001101110100101111", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001", - "1100000001000000011000110111010010111100011010100111", - "110000000100000001100011011101001011110001101010011111", - "11000000010000000110001101110100101111000110101001111110", - "1100000001000000011000110111010010111100011010100111111011", - "110000000100000001100011011101001011110001101010011111101111", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 3, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "110", - "110000", - "110000000", - "110000000100", - "110000000100000", - "110000000100000001", - "110000000100000001100", - "110000000100000001100011", - "110000000100000001100011011", - "110000000100000001100011011101", - "110000000100000001100011011101001", - "110000000100000001100011011101001011", - "110000000100000001100011011101001011110", - "110000000100000001100011011101001011110001", - "110000000100000001100011011101001011110001101", - "110000000100000001100011011101001011110001101010", - "110000000100000001100011011101001011110001101010011", - "110000000100000001100011011101001011110001101010011111", - "110000000100000001100011011101001011110001101010011111101", - "110000000100000001100011011101001011110001101010011111101111", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 4, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100", - "11000000", - "110000000100", - "1100000001000000", - "11000000010000000110", - "110000000100000001100011", - "1100000001000000011000110111", - "11000000010000000110001101110100", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 8, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000", - "1100000001000000", - "110000000100000001100011", - "11000000010000000110001101110100", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 10, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001", - "11000000010000000110", - "110000000100000001100011011101", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 11, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010", - "1100000001000000011000", - "110000000100000001100011011101001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010100111111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 16, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000", - "11000000010000000110001101110100", - "110000000100000001100011011101001011110001101010" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 31, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000011000110111010", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 32, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010000000110001101110100" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 1, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1", - "11", - "110", - "1100", - "11000", - "110000", - "1100000", - "11000000", - "110000000", - "1100000001", - "11000000010", - "110000000100", - "1100000001000", - "11000000010000", - "110000000100000", - "1100000001000000", - "11000000010000000", - "110000000100000001", - "1100000001000000011", - "11000000010000000110", - "110000000100000001100", - "1100000001000000011000", - "11000000010000000110001", - "110000000100000001100011", - "1100000001000000011000110", - "11000000010000000110001101", - "110000000100000001100011011", - "1100000001000000011000110111", - "11000000010000000110001101110", - "110000000100000001100011011101", - "1100000001000000011000110111010", - "11000000010000000110001101110100", - "110000000100000001100011011101001", - "1100000001000000011000110111010010", - "11000000010000000110001101110100101", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111", - "11000000010000000110001101110100101111", - "110000000100000001100011011101001011110", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000", - "110000000100000001100011011101001011110001", - "1100000001000000011000110111010010111100011", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101", - "1100000001000000011000110111010010111100011010", - "11000000010000000110001101110100101111000110101", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111", - "110000000100000001100011011101001011110001101010011111", - "1100000001000000011000110111010010111100011010100111111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101", - "1100000001000000011000110111010010111100011010100111111011", - "11000000010000000110001101110100101111000110101001111110111", - "110000000100000001100011011101001011110001101010011111101111", - "1100000001000000011000110111010010111100011010100111111011111", - "11000000010000000110001101110100101111000110101001111110111110", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 2, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11", - "1100", - "110000", - "11000000", - "1100000001", - "110000000100", - "11000000010000", - "1100000001000000", - "110000000100000001", - "11000000010000000110", - "1100000001000000011000", - "110000000100000001100011", - "11000000010000000110001101", - "1100000001000000011000110111", - "110000000100000001100011011101", - "11000000010000000110001101110100", - "1100000001000000011000110111010010", - "110000000100000001100011011101001011", - "11000000010000000110001101110100101111", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001", - "1100000001000000011000110111010010111100011010100111", - "110000000100000001100011011101001011110001101010011111", - "11000000010000000110001101110100101111000110101001111110", - "1100000001000000011000110111010010111100011010100111111011", - "110000000100000001100011011101001011110001101010011111101111", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 3, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "110", - "110000", - "110000000", - "110000000100", - "110000000100000", - "110000000100000001", - "110000000100000001100", - "110000000100000001100011", - "110000000100000001100011011", - "110000000100000001100011011101", - "110000000100000001100011011101001", - "110000000100000001100011011101001011", - "110000000100000001100011011101001011110", - "110000000100000001100011011101001011110001", - "110000000100000001100011011101001011110001101", - "110000000100000001100011011101001011110001101010", - "110000000100000001100011011101001011110001101010011", - "110000000100000001100011011101001011110001101010011111", - "110000000100000001100011011101001011110001101010011111101", - "110000000100000001100011011101001011110001101010011111101111", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 4, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100", - "11000000", - "110000000100", - "1100000001000000", - "11000000010000000110", - "110000000100000001100011", - "1100000001000000011000110111", - "11000000010000000110001101110100", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 8, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000", - "1100000001000000", - "110000000100000001100011", - "11000000010000000110001101110100", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 10, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001", - "11000000010000000110", - "110000000100000001100011011101", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 11, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010", - "1100000001000000011000", - "110000000100000001100011011101001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010100111111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 16, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000", - "11000000010000000110001101110100", - "110000000100000001100011011101001011110001101010" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 31, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000011000110111010", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 32, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010000000110001101110100" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 1, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1", - "11", - "110", - "1100", - "11000", - "110000", - "1100000", - "11000000", - "110000000", - "1100000001", - "11000000010", - "110000000100", - "1100000001000", - "11000000010000", - "110000000100000", - "1100000001000000", - "11000000010000000", - "110000000100000001", - "1100000001000000011", - "11000000010000000110", - "110000000100000001100", - "1100000001000000011000", - "11000000010000000110001", - "110000000100000001100011", - "1100000001000000011000110", - "11000000010000000110001101", - "110000000100000001100011011", - "1100000001000000011000110111", - "11000000010000000110001101110", - "110000000100000001100011011101", - "1100000001000000011000110111010", - "11000000010000000110001101110100", - "110000000100000001100011011101001", - "1100000001000000011000110111010010", - "11000000010000000110001101110100101", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111", - "11000000010000000110001101110100101111", - "110000000100000001100011011101001011110", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000", - "110000000100000001100011011101001011110001", - "1100000001000000011000110111010010111100011", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101", - "1100000001000000011000110111010010111100011010", - "11000000010000000110001101110100101111000110101", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111", - "110000000100000001100011011101001011110001101010011111", - "1100000001000000011000110111010010111100011010100111111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101", - "1100000001000000011000110111010010111100011010100111111011", - "11000000010000000110001101110100101111000110101001111110111", - "110000000100000001100011011101001011110001101010011111101111", - "1100000001000000011000110111010010111100011010100111111011111", - "11000000010000000110001101110100101111000110101001111110111110", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 2, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11", - "1100", - "110000", - "11000000", - "1100000001", - "110000000100", - "11000000010000", - "1100000001000000", - "110000000100000001", - "11000000010000000110", - "1100000001000000011000", - "110000000100000001100011", - "11000000010000000110001101", - "1100000001000000011000110111", - "110000000100000001100011011101", - "11000000010000000110001101110100", - "1100000001000000011000110111010010", - "110000000100000001100011011101001011", - "11000000010000000110001101110100101111", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001", - "1100000001000000011000110111010010111100011010100111", - "110000000100000001100011011101001011110001101010011111", - "11000000010000000110001101110100101111000110101001111110", - "1100000001000000011000110111010010111100011010100111111011", - "110000000100000001100011011101001011110001101010011111101111", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 3, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "110", - "110000", - "110000000", - "110000000100", - "110000000100000", - "110000000100000001", - "110000000100000001100", - "110000000100000001100011", - "110000000100000001100011011", - "110000000100000001100011011101", - "110000000100000001100011011101001", - "110000000100000001100011011101001011", - "110000000100000001100011011101001011110", - "110000000100000001100011011101001011110001", - "110000000100000001100011011101001011110001101", - "110000000100000001100011011101001011110001101010", - "110000000100000001100011011101001011110001101010011", - "110000000100000001100011011101001011110001101010011111", - "110000000100000001100011011101001011110001101010011111101", - "110000000100000001100011011101001011110001101010011111101111", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 4, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100", - "11000000", - "110000000100", - "1100000001000000", - "11000000010000000110", - "110000000100000001100011", - "1100000001000000011000110111", - "11000000010000000110001101110100", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 8, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000", - "1100000001000000", - "110000000100000001100011", - "11000000010000000110001101110100", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 10, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001", - "11000000010000000110", - "110000000100000001100011011101", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 11, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010", - "1100000001000000011000", - "110000000100000001100011011101001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010100111111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 16, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000", - "11000000010000000110001101110100", - "110000000100000001100011011101001011110001101010" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 31, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000011000110111010", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 32, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010000000110001101110100" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 1, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1", - "11", - "110", - "1100", - "11000", - "110000", - "1100000", - "11000000", - "110000000", - "1100000001", - "11000000010", - "110000000100", - "1100000001000", - "11000000010000", - "110000000100000", - "1100000001000000", - "11000000010000000", - "110000000100000001", - "1100000001000000011", - "11000000010000000110", - "110000000100000001100", - "1100000001000000011000", - "11000000010000000110001", - "110000000100000001100011", - "1100000001000000011000110", - "11000000010000000110001101", - "110000000100000001100011011", - "1100000001000000011000110111", - "11000000010000000110001101110", - "110000000100000001100011011101", - "1100000001000000011000110111010", - "11000000010000000110001101110100", - "110000000100000001100011011101001", - "1100000001000000011000110111010010", - "11000000010000000110001101110100101", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111", - "11000000010000000110001101110100101111", - "110000000100000001100011011101001011110", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000", - "110000000100000001100011011101001011110001", - "1100000001000000011000110111010010111100011", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101", - "1100000001000000011000110111010010111100011010", - "11000000010000000110001101110100101111000110101", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111", - "110000000100000001100011011101001011110001101010011111", - "1100000001000000011000110111010010111100011010100111111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101", - "1100000001000000011000110111010010111100011010100111111011", - "11000000010000000110001101110100101111000110101001111110111", - "110000000100000001100011011101001011110001101010011111101111", - "1100000001000000011000110111010010111100011010100111111011111", - "11000000010000000110001101110100101111000110101001111110111110", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 2, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11", - "1100", - "110000", - "11000000", - "1100000001", - "110000000100", - "11000000010000", - "1100000001000000", - "110000000100000001", - "11000000010000000110", - "1100000001000000011000", - "110000000100000001100011", - "11000000010000000110001101", - "1100000001000000011000110111", - "110000000100000001100011011101", - "11000000010000000110001101110100", - "1100000001000000011000110111010010", - "110000000100000001100011011101001011", - "11000000010000000110001101110100101111", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001", - "1100000001000000011000110111010010111100011010100111", - "110000000100000001100011011101001011110001101010011111", - "11000000010000000110001101110100101111000110101001111110", - "1100000001000000011000110111010010111100011010100111111011", - "110000000100000001100011011101001011110001101010011111101111", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 3, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "110", - "110000", - "110000000", - "110000000100", - "110000000100000", - "110000000100000001", - "110000000100000001100", - "110000000100000001100011", - "110000000100000001100011011", - "110000000100000001100011011101", - "110000000100000001100011011101001", - "110000000100000001100011011101001011", - "110000000100000001100011011101001011110", - "110000000100000001100011011101001011110001", - "110000000100000001100011011101001011110001101", - "110000000100000001100011011101001011110001101010", - "110000000100000001100011011101001011110001101010011", - "110000000100000001100011011101001011110001101010011111", - "110000000100000001100011011101001011110001101010011111101", - "110000000100000001100011011101001011110001101010011111101111", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 4, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100", - "11000000", - "110000000100", - "1100000001000000", - "11000000010000000110", - "110000000100000001100011", - "1100000001000000011000110111", - "11000000010000000110001101110100", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 8, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000", - "1100000001000000", - "110000000100000001100011", - "11000000010000000110001101110100", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 10, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001", - "11000000010000000110", - "110000000100000001100011011101", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 11, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010", - "1100000001000000011000", - "110000000100000001100011011101001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010100111111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 16, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000", - "11000000010000000110001101110100", - "110000000100000001100011011101001011110001101010" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 31, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000011000110111010", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 32, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010000000110001101110100" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 1, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1", - "11", - "110", - "1100", - "11000", - "110000", - "1100000", - "11000000", - "110000000", - "1100000001", - "11000000010", - "110000000100", - "1100000001000", - "11000000010000", - "110000000100000", - "1100000001000000", - "11000000010000000", - "110000000100000001", - "1100000001000000011", - "11000000010000000110", - "110000000100000001100", - "1100000001000000011000", - "11000000010000000110001", - "110000000100000001100011", - "1100000001000000011000110", - "11000000010000000110001101", - "110000000100000001100011011", - "1100000001000000011000110111", - "11000000010000000110001101110", - "110000000100000001100011011101", - "1100000001000000011000110111010", - "11000000010000000110001101110100", - "110000000100000001100011011101001", - "1100000001000000011000110111010010", - "11000000010000000110001101110100101", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111", - "11000000010000000110001101110100101111", - "110000000100000001100011011101001011110", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000", - "110000000100000001100011011101001011110001", - "1100000001000000011000110111010010111100011", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101", - "1100000001000000011000110111010010111100011010", - "11000000010000000110001101110100101111000110101", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111", - "110000000100000001100011011101001011110001101010011111", - "1100000001000000011000110111010010111100011010100111111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101", - "1100000001000000011000110111010010111100011010100111111011", - "11000000010000000110001101110100101111000110101001111110111", - "110000000100000001100011011101001011110001101010011111101111", - "1100000001000000011000110111010010111100011010100111111011111", - "11000000010000000110001101110100101111000110101001111110111110", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 2, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11", - "1100", - "110000", - "11000000", - "1100000001", - "110000000100", - "11000000010000", - "1100000001000000", - "110000000100000001", - "11000000010000000110", - "1100000001000000011000", - "110000000100000001100011", - "11000000010000000110001101", - "1100000001000000011000110111", - "110000000100000001100011011101", - "11000000010000000110001101110100", - "1100000001000000011000110111010010", - "110000000100000001100011011101001011", - "11000000010000000110001101110100101111", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001", - "1100000001000000011000110111010010111100011010100111", - "110000000100000001100011011101001011110001101010011111", - "11000000010000000110001101110100101111000110101001111110", - "1100000001000000011000110111010010111100011010100111111011", - "110000000100000001100011011101001011110001101010011111101111", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 3, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "110", - "110000", - "110000000", - "110000000100", - "110000000100000", - "110000000100000001", - "110000000100000001100", - "110000000100000001100011", - "110000000100000001100011011", - "110000000100000001100011011101", - "110000000100000001100011011101001", - "110000000100000001100011011101001011", - "110000000100000001100011011101001011110", - "110000000100000001100011011101001011110001", - "110000000100000001100011011101001011110001101", - "110000000100000001100011011101001011110001101010", - "110000000100000001100011011101001011110001101010011", - "110000000100000001100011011101001011110001101010011111", - "110000000100000001100011011101001011110001101010011111101", - "110000000100000001100011011101001011110001101010011111101111", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 4, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100", - "11000000", - "110000000100", - "1100000001000000", - "11000000010000000110", - "110000000100000001100011", - "1100000001000000011000110111", - "11000000010000000110001101110100", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 8, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000", - "1100000001000000", - "110000000100000001100011", - "11000000010000000110001101110100", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 10, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001", - "11000000010000000110", - "110000000100000001100011011101", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 11, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010", - "1100000001000000011000", - "110000000100000001100011011101001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010100111111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 16, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000", - "11000000010000000110001101110100", - "110000000100000001100011011101001011110001101010" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 31, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000011000110111010", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 32, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010000000110001101110100" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 1, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1", - "11", - "110", - "1100", - "11000", - "110000", - "1100000", - "11000000", - "110000000", - "1100000001", - "11000000010", - "110000000100", - "1100000001000", - "11000000010000", - "110000000100000", - "1100000001000000", - "11000000010000000", - "110000000100000001", - "1100000001000000011", - "11000000010000000110", - "110000000100000001100", - "1100000001000000011000", - "11000000010000000110001", - "110000000100000001100011", - "1100000001000000011000110", - "11000000010000000110001101", - "110000000100000001100011011", - "1100000001000000011000110111", - "11000000010000000110001101110", - "110000000100000001100011011101", - "1100000001000000011000110111010", - "11000000010000000110001101110100", - "110000000100000001100011011101001", - "1100000001000000011000110111010010", - "11000000010000000110001101110100101", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111", - "11000000010000000110001101110100101111", - "110000000100000001100011011101001011110", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000", - "110000000100000001100011011101001011110001", - "1100000001000000011000110111010010111100011", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101", - "1100000001000000011000110111010010111100011010", - "11000000010000000110001101110100101111000110101", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111", - "110000000100000001100011011101001011110001101010011111", - "1100000001000000011000110111010010111100011010100111111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101", - "1100000001000000011000110111010010111100011010100111111011", - "11000000010000000110001101110100101111000110101001111110111", - "110000000100000001100011011101001011110001101010011111101111", - "1100000001000000011000110111010010111100011010100111111011111", - "11000000010000000110001101110100101111000110101001111110111110", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 2, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11", - "1100", - "110000", - "11000000", - "1100000001", - "110000000100", - "11000000010000", - "1100000001000000", - "110000000100000001", - "11000000010000000110", - "1100000001000000011000", - "110000000100000001100011", - "11000000010000000110001101", - "1100000001000000011000110111", - "110000000100000001100011011101", - "11000000010000000110001101110100", - "1100000001000000011000110111010010", - "110000000100000001100011011101001011", - "11000000010000000110001101110100101111", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001", - "1100000001000000011000110111010010111100011010100111", - "110000000100000001100011011101001011110001101010011111", - "11000000010000000110001101110100101111000110101001111110", - "1100000001000000011000110111010010111100011010100111111011", - "110000000100000001100011011101001011110001101010011111101111", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 3, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "110", - "110000", - "110000000", - "110000000100", - "110000000100000", - "110000000100000001", - "110000000100000001100", - "110000000100000001100011", - "110000000100000001100011011", - "110000000100000001100011011101", - "110000000100000001100011011101001", - "110000000100000001100011011101001011", - "110000000100000001100011011101001011110", - "110000000100000001100011011101001011110001", - "110000000100000001100011011101001011110001101", - "110000000100000001100011011101001011110001101010", - "110000000100000001100011011101001011110001101010011", - "110000000100000001100011011101001011110001101010011111", - "110000000100000001100011011101001011110001101010011111101", - "110000000100000001100011011101001011110001101010011111101111", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 4, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100", - "11000000", - "110000000100", - "1100000001000000", - "11000000010000000110", - "110000000100000001100011", - "1100000001000000011000110111", - "11000000010000000110001101110100", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 8, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000", - "1100000001000000", - "110000000100000001100011", - "11000000010000000110001101110100", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 10, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001", - "11000000010000000110", - "110000000100000001100011011101", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 11, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010", - "1100000001000000011000", - "110000000100000001100011011101001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010100111111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 16, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000", - "11000000010000000110001101110100", - "110000000100000001100011011101001011110001101010" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 31, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000011000110111010", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 32, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010000000110001101110100" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 1, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1", - "11", - "110", - "1100", - "11000", - "110000", - "1100000", - "11000000", - "110000000", - "1100000001", - "11000000010", - "110000000100", - "1100000001000", - "11000000010000", - "110000000100000", - "1100000001000000", - "11000000010000000", - "110000000100000001", - "1100000001000000011", - "11000000010000000110", - "110000000100000001100", - "1100000001000000011000", - "11000000010000000110001", - "110000000100000001100011", - "1100000001000000011000110", - "11000000010000000110001101", - "110000000100000001100011011", - "1100000001000000011000110111", - "11000000010000000110001101110", - "110000000100000001100011011101", - "1100000001000000011000110111010", - "11000000010000000110001101110100", - "110000000100000001100011011101001", - "1100000001000000011000110111010010", - "11000000010000000110001101110100101", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111", - "11000000010000000110001101110100101111", - "110000000100000001100011011101001011110", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000", - "110000000100000001100011011101001011110001", - "1100000001000000011000110111010010111100011", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101", - "1100000001000000011000110111010010111100011010", - "11000000010000000110001101110100101111000110101", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111", - "110000000100000001100011011101001011110001101010011111", - "1100000001000000011000110111010010111100011010100111111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101", - "1100000001000000011000110111010010111100011010100111111011", - "11000000010000000110001101110100101111000110101001111110111", - "110000000100000001100011011101001011110001101010011111101111", - "1100000001000000011000110111010010111100011010100111111011111", - "11000000010000000110001101110100101111000110101001111110111110", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 2, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11", - "1100", - "110000", - "11000000", - "1100000001", - "110000000100", - "11000000010000", - "1100000001000000", - "110000000100000001", - "11000000010000000110", - "1100000001000000011000", - "110000000100000001100011", - "11000000010000000110001101", - "1100000001000000011000110111", - "110000000100000001100011011101", - "11000000010000000110001101110100", - "1100000001000000011000110111010010", - "110000000100000001100011011101001011", - "11000000010000000110001101110100101111", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001", - "1100000001000000011000110111010010111100011010100111", - "110000000100000001100011011101001011110001101010011111", - "11000000010000000110001101110100101111000110101001111110", - "1100000001000000011000110111010010111100011010100111111011", - "110000000100000001100011011101001011110001101010011111101111", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 3, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "110", - "110000", - "110000000", - "110000000100", - "110000000100000", - "110000000100000001", - "110000000100000001100", - "110000000100000001100011", - "110000000100000001100011011", - "110000000100000001100011011101", - "110000000100000001100011011101001", - "110000000100000001100011011101001011", - "110000000100000001100011011101001011110", - "110000000100000001100011011101001011110001", - "110000000100000001100011011101001011110001101", - "110000000100000001100011011101001011110001101010", - "110000000100000001100011011101001011110001101010011", - "110000000100000001100011011101001011110001101010011111", - "110000000100000001100011011101001011110001101010011111101", - "110000000100000001100011011101001011110001101010011111101111", - "110000000100000001100011011101001011110001101010011111101111101" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 4, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100", - "11000000", - "110000000100", - "1100000001000000", - "11000000010000000110", - "110000000100000001100011", - "1100000001000000011000110111", - "11000000010000000110001101110100", - "110000000100000001100011011101001011", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110", - "110000000100000001100011011101001011110001101010", - "1100000001000000011000110111010010111100011010100111", - "11000000010000000110001101110100101111000110101001111110", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 8, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000", - "1100000001000000", - "110000000100000001100011", - "11000000010000000110001101110100", - "1100000001000000011000110111010010111100", - "110000000100000001100011011101001011110001101010", - "11000000010000000110001101110100101111000110101001111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 10, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001", - "11000000010000000110", - "110000000100000001100011011101", - "1100000001000000011000110111010010111100", - "11000000010000000110001101110100101111000110101001", - "110000000100000001100011011101001011110001101010011111101111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 11, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010", - "1100000001000000011000", - "110000000100000001100011011101001", - "11000000010000000110001101110100101111000110", - "1100000001000000011000110111010010111100011010100111111" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 16, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000", - "11000000010000000110001101110100", - "110000000100000001100011011101001011110001101010" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 31, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "1100000001000000011000110111010", - "11000000010000000110001101110100101111000110101001111110111110" - } -}, -{ - .value = 32.77700000000000102, - .sparsity = 32, - .expectEdges = { - "root", - "1100000001000000011000110111010010111100011010100111111011111010", - "11000000010000000110001101110100" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1", - "11", - "111", - "1111", - "11111", - "111111", - "1111111", - "11111111", - "111111111", - "1111111111", - "11111111111", - "111111111110", - "1111111111101", - "11111111111011", - "111111111110111", - "1111111111101111", - "11111111111011111", - "111111111110111111", - "1111111111101111111", - "11111111111011111111", - "111111111110111111111", - "1111111111101111111111", - "11111111111011111111111", - "111111111110111111111111", - "1111111111101111111111111", - "11111111111011111111111111", - "111111111110111111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111", - "111111111110111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111", - "1111111111101111111111111111111111", - "11111111111011111111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111", - "11111111111011111111111111111111111111", - "111111111110111111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111", - "111111111110111111111111111111111111111111", - "1111111111101111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11", - "1111", - "111111", - "11111111", - "1111111111", - "111111111110", - "11111111111011", - "1111111111101111", - "111111111110111111", - "11111111111011111111", - "1111111111101111111111", - "111111111110111111111111", - "11111111111011111111111111", - "1111111111101111111111111111", - "111111111110111111111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111", - "111111111110111111111111111111111111", - "11111111111011111111111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "111", - "111111", - "111111111", - "111111111110", - "111111111110111", - "111111111110111111", - "111111111110111111111", - "111111111110111111111111", - "111111111110111111111111111", - "111111111110111111111111111111", - "111111111110111111111111111111111", - "111111111110111111111111111111111111", - "111111111110111111111111111111111111111", - "111111111110111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111", - "11111111", - "111111111110", - "1111111111101111", - "11111111111011111111", - "111111111110111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111", - "1111111111101111", - "111111111110111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111", - "11111111111011111111", - "111111111110111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111", - "1111111111101111111111", - "111111111110111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1", - "11", - "111", - "1111", - "11111", - "111111", - "1111111", - "11111111", - "111111111", - "1111111111", - "11111111111", - "111111111110", - "1111111111101", - "11111111111011", - "111111111110111", - "1111111111101111", - "11111111111011111", - "111111111110111111", - "1111111111101111111", - "11111111111011111111", - "111111111110111111111", - "1111111111101111111111", - "11111111111011111111111", - "111111111110111111111111", - "1111111111101111111111111", - "11111111111011111111111111", - "111111111110111111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111", - "111111111110111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111", - "1111111111101111111111111111111111", - "11111111111011111111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111", - "11111111111011111111111111111111111111", - "111111111110111111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111", - "111111111110111111111111111111111111111111", - "1111111111101111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11", - "1111", - "111111", - "11111111", - "1111111111", - "111111111110", - "11111111111011", - "1111111111101111", - "111111111110111111", - "11111111111011111111", - "1111111111101111111111", - "111111111110111111111111", - "11111111111011111111111111", - "1111111111101111111111111111", - "111111111110111111111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111", - "111111111110111111111111111111111111", - "11111111111011111111111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "111", - "111111", - "111111111", - "111111111110", - "111111111110111", - "111111111110111111", - "111111111110111111111", - "111111111110111111111111", - "111111111110111111111111111", - "111111111110111111111111111111", - "111111111110111111111111111111111", - "111111111110111111111111111111111111", - "111111111110111111111111111111111111111", - "111111111110111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111", - "11111111", - "111111111110", - "1111111111101111", - "11111111111011111111", - "111111111110111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111", - "1111111111101111", - "111111111110111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111", - "11111111111011111111", - "111111111110111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111", - "1111111111101111111111", - "111111111110111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1", - "11", - "111", - "1111", - "11111", - "111111", - "1111111", - "11111111", - "111111111", - "1111111111", - "11111111111", - "111111111110", - "1111111111101", - "11111111111011", - "111111111110111", - "1111111111101111", - "11111111111011111", - "111111111110111111", - "1111111111101111111", - "11111111111011111111", - "111111111110111111111", - "1111111111101111111111", - "11111111111011111111111", - "111111111110111111111111", - "1111111111101111111111111", - "11111111111011111111111111", - "111111111110111111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111", - "111111111110111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111", - "1111111111101111111111111111111111", - "11111111111011111111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111", - "11111111111011111111111111111111111111", - "111111111110111111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111", - "111111111110111111111111111111111111111111", - "1111111111101111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11", - "1111", - "111111", - "11111111", - "1111111111", - "111111111110", - "11111111111011", - "1111111111101111", - "111111111110111111", - "11111111111011111111", - "1111111111101111111111", - "111111111110111111111111", - "11111111111011111111111111", - "1111111111101111111111111111", - "111111111110111111111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111", - "111111111110111111111111111111111111", - "11111111111011111111111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "111", - "111111", - "111111111", - "111111111110", - "111111111110111", - "111111111110111111", - "111111111110111111111", - "111111111110111111111111", - "111111111110111111111111111", - "111111111110111111111111111111", - "111111111110111111111111111111111", - "111111111110111111111111111111111111", - "111111111110111111111111111111111111111", - "111111111110111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111", - "11111111", - "111111111110", - "1111111111101111", - "11111111111011111111", - "111111111110111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111", - "1111111111101111", - "111111111110111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111", - "11111111111011111111", - "111111111110111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111", - "1111111111101111111111", - "111111111110111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1", - "11", - "111", - "1111", - "11111", - "111111", - "1111111", - "11111111", - "111111111", - "1111111111", - "11111111111", - "111111111110", - "1111111111101", - "11111111111011", - "111111111110111", - "1111111111101111", - "11111111111011111", - "111111111110111111", - "1111111111101111111", - "11111111111011111111", - "111111111110111111111", - "1111111111101111111111", - "11111111111011111111111", - "111111111110111111111111", - "1111111111101111111111111", - "11111111111011111111111111", - "111111111110111111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111", - "111111111110111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111", - "1111111111101111111111111111111111", - "11111111111011111111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111", - "11111111111011111111111111111111111111", - "111111111110111111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111", - "111111111110111111111111111111111111111111", - "1111111111101111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11", - "1111", - "111111", - "11111111", - "1111111111", - "111111111110", - "11111111111011", - "1111111111101111", - "111111111110111111", - "11111111111011111111", - "1111111111101111111111", - "111111111110111111111111", - "11111111111011111111111111", - "1111111111101111111111111111", - "111111111110111111111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111", - "111111111110111111111111111111111111", - "11111111111011111111111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "111", - "111111", - "111111111", - "111111111110", - "111111111110111", - "111111111110111111", - "111111111110111111111", - "111111111110111111111111", - "111111111110111111111111111", - "111111111110111111111111111111", - "111111111110111111111111111111111", - "111111111110111111111111111111111111", - "111111111110111111111111111111111111111", - "111111111110111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111", - "11111111", - "111111111110", - "1111111111101111", - "11111111111011111111", - "111111111110111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111", - "1111111111101111", - "111111111110111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111", - "11111111111011111111", - "111111111110111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111", - "1111111111101111111111", - "111111111110111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1", - "11", - "111", - "1111", - "11111", - "111111", - "1111111", - "11111111", - "111111111", - "1111111111", - "11111111111", - "111111111110", - "1111111111101", - "11111111111011", - "111111111110111", - "1111111111101111", - "11111111111011111", - "111111111110111111", - "1111111111101111111", - "11111111111011111111", - "111111111110111111111", - "1111111111101111111111", - "11111111111011111111111", - "111111111110111111111111", - "1111111111101111111111111", - "11111111111011111111111111", - "111111111110111111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111", - "111111111110111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111", - "1111111111101111111111111111111111", - "11111111111011111111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111", - "11111111111011111111111111111111111111", - "111111111110111111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111", - "111111111110111111111111111111111111111111", - "1111111111101111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11", - "1111", - "111111", - "11111111", - "1111111111", - "111111111110", - "11111111111011", - "1111111111101111", - "111111111110111111", - "11111111111011111111", - "1111111111101111111111", - "111111111110111111111111", - "11111111111011111111111111", - "1111111111101111111111111111", - "111111111110111111111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111", - "111111111110111111111111111111111111", - "11111111111011111111111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "111", - "111111", - "111111111", - "111111111110", - "111111111110111", - "111111111110111111", - "111111111110111111111", - "111111111110111111111111", - "111111111110111111111111111", - "111111111110111111111111111111", - "111111111110111111111111111111111", - "111111111110111111111111111111111111", - "111111111110111111111111111111111111111", - "111111111110111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111", - "11111111", - "111111111110", - "1111111111101111", - "11111111111011111111", - "111111111110111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111", - "1111111111101111", - "111111111110111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111", - "11111111111011111111", - "111111111110111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111", - "1111111111101111111111", - "111111111110111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1", - "11", - "111", - "1111", - "11111", - "111111", - "1111111", - "11111111", - "111111111", - "1111111111", - "11111111111", - "111111111110", - "1111111111101", - "11111111111011", - "111111111110111", - "1111111111101111", - "11111111111011111", - "111111111110111111", - "1111111111101111111", - "11111111111011111111", - "111111111110111111111", - "1111111111101111111111", - "11111111111011111111111", - "111111111110111111111111", - "1111111111101111111111111", - "11111111111011111111111111", - "111111111110111111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111", - "111111111110111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111", - "1111111111101111111111111111111111", - "11111111111011111111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111", - "11111111111011111111111111111111111111", - "111111111110111111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111", - "111111111110111111111111111111111111111111", - "1111111111101111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11", - "1111", - "111111", - "11111111", - "1111111111", - "111111111110", - "11111111111011", - "1111111111101111", - "111111111110111111", - "11111111111011111111", - "1111111111101111111111", - "111111111110111111111111", - "11111111111011111111111111", - "1111111111101111111111111111", - "111111111110111111111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111", - "111111111110111111111111111111111111", - "11111111111011111111111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "111", - "111111", - "111111111", - "111111111110", - "111111111110111", - "111111111110111111", - "111111111110111111111", - "111111111110111111111111", - "111111111110111111111111111", - "111111111110111111111111111111", - "111111111110111111111111111111111", - "111111111110111111111111111111111111", - "111111111110111111111111111111111111111", - "111111111110111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111", - "11111111", - "111111111110", - "1111111111101111", - "11111111111011111111", - "111111111110111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111", - "1111111111101111", - "111111111110111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111", - "11111111111011111111", - "111111111110111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111", - "1111111111101111111111", - "111111111110111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1", - "11", - "111", - "1111", - "11111", - "111111", - "1111111", - "11111111", - "111111111", - "1111111111", - "11111111111", - "111111111110", - "1111111111101", - "11111111111011", - "111111111110111", - "1111111111101111", - "11111111111011111", - "111111111110111111", - "1111111111101111111", - "11111111111011111111", - "111111111110111111111", - "1111111111101111111111", - "11111111111011111111111", - "111111111110111111111111", - "1111111111101111111111111", - "11111111111011111111111111", - "111111111110111111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111", - "111111111110111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111", - "1111111111101111111111111111111111", - "11111111111011111111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111", - "11111111111011111111111111111111111111", - "111111111110111111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111", - "111111111110111111111111111111111111111111", - "1111111111101111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11", - "1111", - "111111", - "11111111", - "1111111111", - "111111111110", - "11111111111011", - "1111111111101111", - "111111111110111111", - "11111111111011111111", - "1111111111101111111111", - "111111111110111111111111", - "11111111111011111111111111", - "1111111111101111111111111111", - "111111111110111111111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111", - "111111111110111111111111111111111111", - "11111111111011111111111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "111", - "111111", - "111111111", - "111111111110", - "111111111110111", - "111111111110111111", - "111111111110111111111", - "111111111110111111111111", - "111111111110111111111111111", - "111111111110111111111111111111", - "111111111110111111111111111111111", - "111111111110111111111111111111111111", - "111111111110111111111111111111111111111", - "111111111110111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111", - "11111111", - "111111111110", - "1111111111101111", - "11111111111011111111", - "111111111110111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111", - "1111111111101111", - "111111111110111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111", - "11111111111011111111", - "111111111110111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111", - "1111111111101111111111", - "111111111110111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 1, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1", - "11", - "111", - "1111", - "11111", - "111111", - "1111111", - "11111111", - "111111111", - "1111111111", - "11111111111", - "111111111110", - "1111111111101", - "11111111111011", - "111111111110111", - "1111111111101111", - "11111111111011111", - "111111111110111111", - "1111111111101111111", - "11111111111011111111", - "111111111110111111111", - "1111111111101111111111", - "11111111111011111111111", - "111111111110111111111111", - "1111111111101111111111111", - "11111111111011111111111111", - "111111111110111111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111", - "111111111110111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111", - "1111111111101111111111111111111111", - "11111111111011111111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111", - "11111111111011111111111111111111111111", - "111111111110111111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111", - "111111111110111111111111111111111111111111", - "1111111111101111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 2, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11", - "1111", - "111111", - "11111111", - "1111111111", - "111111111110", - "11111111111011", - "1111111111101111", - "111111111110111111", - "11111111111011111111", - "1111111111101111111111", - "111111111110111111111111", - "11111111111011111111111111", - "1111111111101111111111111111", - "111111111110111111111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111", - "111111111110111111111111111111111111", - "11111111111011111111111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 3, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "111", - "111111", - "111111111", - "111111111110", - "111111111110111", - "111111111110111111", - "111111111110111111111", - "111111111110111111111111", - "111111111110111111111111111", - "111111111110111111111111111111", - "111111111110111111111111111111111", - "111111111110111111111111111111111111", - "111111111110111111111111111111111111111", - "111111111110111111111111111111111111111111", - "111111111110111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 4, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111", - "11111111", - "111111111110", - "1111111111101111", - "11111111111011111111", - "111111111110111111111111", - "1111111111101111111111111111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 8, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111", - "1111111111101111", - "111111111110111111111111", - "11111111111011111111111111111111", - "1111111111101111111111111111111111111111", - "111111111110111111111111111111111111111111111111", - "11111111111011111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 10, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111", - "11111111111011111111", - "111111111110111111111111111111", - "1111111111101111111111111111111111111111", - "11111111111011111111111111111111111111111111111111", - "111111111110111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 11, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111", - "1111111111101111111111", - "111111111110111111111111111111111", - "11111111111011111111111111111111111111111111", - "1111111111101111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 16, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111", - "11111111111011111111111111111111", - "111111111110111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 31, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "1111111111101111111111111111111", - "11111111111011111111111111111111111111111111111111111111111111" - } -}, -{ - .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, - .sparsity = 32, - .expectEdges = { - "root", - "1111111111101111111111111111111111111111111111111111111111111111", - "11111111111011111111111111111111" - } -}, -{ - .value = DBL_MIN, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000001", - "1000000000010", - "10000000000100", - "100000000001000", - "1000000000010000", - "10000000000100000", - "100000000001000000", - "1000000000010000000", - "10000000000100000000", - "100000000001000000000", - "1000000000010000000000", - "10000000000100000000000", - "100000000001000000000000", - "1000000000010000000000000", - "10000000000100000000000000", - "100000000001000000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000", - "100000000001000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000", - "1000000000010000000000000000000000", - "10000000000100000000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000", - "10000000000100000000000000000000000000", - "100000000001000000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000", - "100000000001000000000000000000000000000000", - "1000000000010000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000001", - "10000000000100", - "1000000000010000", - "100000000001000000", - "10000000000100000000", - "1000000000010000000000", - "100000000001000000000000", - "10000000000100000000000000", - "1000000000010000000000000000", - "100000000001000000000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000", - "100000000001000000000000000000000000", - "10000000000100000000000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000001", - "100000000001000", - "100000000001000000", - "100000000001000000000", - "100000000001000000000000", - "100000000001000000000000000", - "100000000001000000000000000000", - "100000000001000000000000000000000", - "100000000001000000000000000000000000", - "100000000001000000000000000000000000000", - "100000000001000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000001", - "1000000000010000", - "10000000000100000000", - "100000000001000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000010000", - "100000000001000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000100000000", - "100000000001000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000010000000000", - "100000000001000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000001", - "1000000000010", - "10000000000100", - "100000000001000", - "1000000000010000", - "10000000000100000", - "100000000001000000", - "1000000000010000000", - "10000000000100000000", - "100000000001000000000", - "1000000000010000000000", - "10000000000100000000000", - "100000000001000000000000", - "1000000000010000000000000", - "10000000000100000000000000", - "100000000001000000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000", - "100000000001000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000", - "1000000000010000000000000000000000", - "10000000000100000000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000", - "10000000000100000000000000000000000000", - "100000000001000000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000", - "100000000001000000000000000000000000000000", - "1000000000010000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000001", - "10000000000100", - "1000000000010000", - "100000000001000000", - "10000000000100000000", - "1000000000010000000000", - "100000000001000000000000", - "10000000000100000000000000", - "1000000000010000000000000000", - "100000000001000000000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000", - "100000000001000000000000000000000000", - "10000000000100000000000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000001", - "100000000001000", - "100000000001000000", - "100000000001000000000", - "100000000001000000000000", - "100000000001000000000000000", - "100000000001000000000000000000", - "100000000001000000000000000000000", - "100000000001000000000000000000000000", - "100000000001000000000000000000000000000", - "100000000001000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000001", - "1000000000010000", - "10000000000100000000", - "100000000001000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000010000", - "100000000001000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000100000000", - "100000000001000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000010000000000", - "100000000001000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000001", - "1000000000010", - "10000000000100", - "100000000001000", - "1000000000010000", - "10000000000100000", - "100000000001000000", - "1000000000010000000", - "10000000000100000000", - "100000000001000000000", - "1000000000010000000000", - "10000000000100000000000", - "100000000001000000000000", - "1000000000010000000000000", - "10000000000100000000000000", - "100000000001000000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000", - "100000000001000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000", - "1000000000010000000000000000000000", - "10000000000100000000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000", - "10000000000100000000000000000000000000", - "100000000001000000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000", - "100000000001000000000000000000000000000000", - "1000000000010000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000001", - "10000000000100", - "1000000000010000", - "100000000001000000", - "10000000000100000000", - "1000000000010000000000", - "100000000001000000000000", - "10000000000100000000000000", - "1000000000010000000000000000", - "100000000001000000000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000", - "100000000001000000000000000000000000", - "10000000000100000000000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000001", - "100000000001000", - "100000000001000000", - "100000000001000000000", - "100000000001000000000000", - "100000000001000000000000000", - "100000000001000000000000000000", - "100000000001000000000000000000000", - "100000000001000000000000000000000000", - "100000000001000000000000000000000000000", - "100000000001000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000001", - "1000000000010000", - "10000000000100000000", - "100000000001000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000010000", - "100000000001000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000100000000", - "100000000001000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000010000000000", - "100000000001000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000001", - "1000000000010", - "10000000000100", - "100000000001000", - "1000000000010000", - "10000000000100000", - "100000000001000000", - "1000000000010000000", - "10000000000100000000", - "100000000001000000000", - "1000000000010000000000", - "10000000000100000000000", - "100000000001000000000000", - "1000000000010000000000000", - "10000000000100000000000000", - "100000000001000000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000", - "100000000001000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000", - "1000000000010000000000000000000000", - "10000000000100000000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000", - "10000000000100000000000000000000000000", - "100000000001000000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000", - "100000000001000000000000000000000000000000", - "1000000000010000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000001", - "10000000000100", - "1000000000010000", - "100000000001000000", - "10000000000100000000", - "1000000000010000000000", - "100000000001000000000000", - "10000000000100000000000000", - "1000000000010000000000000000", - "100000000001000000000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000", - "100000000001000000000000000000000000", - "10000000000100000000000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000001", - "100000000001000", - "100000000001000000", - "100000000001000000000", - "100000000001000000000000", - "100000000001000000000000000", - "100000000001000000000000000000", - "100000000001000000000000000000000", - "100000000001000000000000000000000000", - "100000000001000000000000000000000000000", - "100000000001000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000001", - "1000000000010000", - "10000000000100000000", - "100000000001000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000010000", - "100000000001000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000100000000", - "100000000001000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000010000000000", - "100000000001000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000001", - "1000000000010", - "10000000000100", - "100000000001000", - "1000000000010000", - "10000000000100000", - "100000000001000000", - "1000000000010000000", - "10000000000100000000", - "100000000001000000000", - "1000000000010000000000", - "10000000000100000000000", - "100000000001000000000000", - "1000000000010000000000000", - "10000000000100000000000000", - "100000000001000000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000", - "100000000001000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000", - "1000000000010000000000000000000000", - "10000000000100000000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000", - "10000000000100000000000000000000000000", - "100000000001000000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000", - "100000000001000000000000000000000000000000", - "1000000000010000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000001", - "10000000000100", - "1000000000010000", - "100000000001000000", - "10000000000100000000", - "1000000000010000000000", - "100000000001000000000000", - "10000000000100000000000000", - "1000000000010000000000000000", - "100000000001000000000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000", - "100000000001000000000000000000000000", - "10000000000100000000000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000001", - "100000000001000", - "100000000001000000", - "100000000001000000000", - "100000000001000000000000", - "100000000001000000000000000", - "100000000001000000000000000000", - "100000000001000000000000000000000", - "100000000001000000000000000000000000", - "100000000001000000000000000000000000000", - "100000000001000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000001", - "1000000000010000", - "10000000000100000000", - "100000000001000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000010000", - "100000000001000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000100000000", - "100000000001000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000010000000000", - "100000000001000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000001", - "1000000000010", - "10000000000100", - "100000000001000", - "1000000000010000", - "10000000000100000", - "100000000001000000", - "1000000000010000000", - "10000000000100000000", - "100000000001000000000", - "1000000000010000000000", - "10000000000100000000000", - "100000000001000000000000", - "1000000000010000000000000", - "10000000000100000000000000", - "100000000001000000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000", - "100000000001000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000", - "1000000000010000000000000000000000", - "10000000000100000000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000", - "10000000000100000000000000000000000000", - "100000000001000000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000", - "100000000001000000000000000000000000000000", - "1000000000010000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000001", - "10000000000100", - "1000000000010000", - "100000000001000000", - "10000000000100000000", - "1000000000010000000000", - "100000000001000000000000", - "10000000000100000000000000", - "1000000000010000000000000000", - "100000000001000000000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000", - "100000000001000000000000000000000000", - "10000000000100000000000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000001", - "100000000001000", - "100000000001000000", - "100000000001000000000", - "100000000001000000000000", - "100000000001000000000000000", - "100000000001000000000000000000", - "100000000001000000000000000000000", - "100000000001000000000000000000000000", - "100000000001000000000000000000000000000", - "100000000001000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000001", - "1000000000010000", - "10000000000100000000", - "100000000001000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000010000", - "100000000001000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000100000000", - "100000000001000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000010000000000", - "100000000001000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000001", - "1000000000010", - "10000000000100", - "100000000001000", - "1000000000010000", - "10000000000100000", - "100000000001000000", - "1000000000010000000", - "10000000000100000000", - "100000000001000000000", - "1000000000010000000000", - "10000000000100000000000", - "100000000001000000000000", - "1000000000010000000000000", - "10000000000100000000000000", - "100000000001000000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000", - "100000000001000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000", - "1000000000010000000000000000000000", - "10000000000100000000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000", - "10000000000100000000000000000000000000", - "100000000001000000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000", - "100000000001000000000000000000000000000000", - "1000000000010000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000001", - "10000000000100", - "1000000000010000", - "100000000001000000", - "10000000000100000000", - "1000000000010000000000", - "100000000001000000000000", - "10000000000100000000000000", - "1000000000010000000000000000", - "100000000001000000000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000", - "100000000001000000000000000000000000", - "10000000000100000000000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000001", - "100000000001000", - "100000000001000000", - "100000000001000000000", - "100000000001000000000000", - "100000000001000000000000000", - "100000000001000000000000000000", - "100000000001000000000000000000000", - "100000000001000000000000000000000000", - "100000000001000000000000000000000000000", - "100000000001000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000001", - "1000000000010000", - "10000000000100000000", - "100000000001000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000010000", - "100000000001000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000100000000", - "100000000001000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000010000000000", - "100000000001000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000001", - "1000000000010", - "10000000000100", - "100000000001000", - "1000000000010000", - "10000000000100000", - "100000000001000000", - "1000000000010000000", - "10000000000100000000", - "100000000001000000000", - "1000000000010000000000", - "10000000000100000000000", - "100000000001000000000000", - "1000000000010000000000000", - "10000000000100000000000000", - "100000000001000000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000", - "100000000001000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000", - "1000000000010000000000000000000000", - "10000000000100000000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000", - "10000000000100000000000000000000000000", - "100000000001000000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000", - "100000000001000000000000000000000000000000", - "1000000000010000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000001", - "10000000000100", - "1000000000010000", - "100000000001000000", - "10000000000100000000", - "1000000000010000000000", - "100000000001000000000000", - "10000000000100000000000000", - "1000000000010000000000000000", - "100000000001000000000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000", - "100000000001000000000000000000000000", - "10000000000100000000000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000001", - "100000000001000", - "100000000001000000", - "100000000001000000000", - "100000000001000000000000", - "100000000001000000000000000", - "100000000001000000000000000000", - "100000000001000000000000000000000", - "100000000001000000000000000000000000", - "100000000001000000000000000000000000000", - "100000000001000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000001", - "1000000000010000", - "10000000000100000000", - "100000000001000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000010000", - "100000000001000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000100000000", - "100000000001000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000010000000000", - "100000000001000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 1, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1", - "10", - "100", - "1000", - "10000", - "100000", - "1000000", - "10000000", - "100000000", - "1000000000", - "10000000000", - "100000000001", - "1000000000010", - "10000000000100", - "100000000001000", - "1000000000010000", - "10000000000100000", - "100000000001000000", - "1000000000010000000", - "10000000000100000000", - "100000000001000000000", - "1000000000010000000000", - "10000000000100000000000", - "100000000001000000000000", - "1000000000010000000000000", - "10000000000100000000000000", - "100000000001000000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000", - "100000000001000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000", - "1000000000010000000000000000000000", - "10000000000100000000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000", - "10000000000100000000000000000000000000", - "100000000001000000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000", - "100000000001000000000000000000000000000000", - "1000000000010000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 2, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10", - "1000", - "100000", - "10000000", - "1000000000", - "100000000001", - "10000000000100", - "1000000000010000", - "100000000001000000", - "10000000000100000000", - "1000000000010000000000", - "100000000001000000000000", - "10000000000100000000000000", - "1000000000010000000000000000", - "100000000001000000000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000", - "100000000001000000000000000000000000", - "10000000000100000000000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 3, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "100", - "100000", - "100000000", - "100000000001", - "100000000001000", - "100000000001000000", - "100000000001000000000", - "100000000001000000000000", - "100000000001000000000000000", - "100000000001000000000000000000", - "100000000001000000000000000000000", - "100000000001000000000000000000000000", - "100000000001000000000000000000000000000", - "100000000001000000000000000000000000000000", - "100000000001000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 4, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000", - "10000000", - "100000000001", - "1000000000010000", - "10000000000100000000", - "100000000001000000000000", - "1000000000010000000000000000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 8, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000", - "1000000000010000", - "100000000001000000000000", - "10000000000100000000000000000000", - "1000000000010000000000000000000000000000", - "100000000001000000000000000000000000000000000000", - "10000000000100000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 10, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000", - "10000000000100000000", - "100000000001000000000000000000", - "1000000000010000000000000000000000000000", - "10000000000100000000000000000000000000000000000000", - "100000000001000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 11, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000", - "1000000000010000000000", - "100000000001000000000000000000000", - "10000000000100000000000000000000000000000000", - "1000000000010000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 16, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000", - "10000000000100000000000000000000", - "100000000001000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 31, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "1000000000010000000000000000000", - "10000000000100000000000000000000000000000000000000000000000000" - } -}, -{ - .value = DBL_MIN, - .sparsity = 32, - .expectEdges = { - "root", - "1000000000010000000000000000000000000000000000000000000000000000", - "10000000000100000000000000000000" - } +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` +// clang-format off +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000000", + "1000000000000", + "10000000000000", + "100000000000000", + "1000000000000000", + "10000000000000000", + "100000000000000000", + "1000000000000000000", + "10000000000000000000", + "100000000000000000000", + "1000000000000000000000", + "10000000000000000000000", + "100000000000000000000000", + "1000000000000000000000000", + "10000000000000000000000000", + "100000000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000", + "1000000000000000000000000000000000", + "10000000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000000", + "10000000000000", + "1000000000000000", + "100000000000000000", + "10000000000000000000", + "1000000000000000000000", + "100000000000000000000000", + "10000000000000000000000000", + "1000000000000000000000000000", + "100000000000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000", + "100000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000000", + "100000000000000", + "100000000000000000", + "100000000000000000000", + "100000000000000000000000", + "100000000000000000000000000", + "100000000000000000000000000000", + "100000000000000000000000000000000", + "100000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000000", + "1000000000000000", + "10000000000000000000", + "100000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000000000", + "100000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000000000000000", + "100000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000000", + "1000000000000", + "10000000000000", + "100000000000000", + "1000000000000000", + "10000000000000000", + "100000000000000000", + "1000000000000000000", + "10000000000000000000", + "100000000000000000000", + "1000000000000000000000", + "10000000000000000000000", + "100000000000000000000000", + "1000000000000000000000000", + "10000000000000000000000000", + "100000000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000", + "1000000000000000000000000000000000", + "10000000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000000", + "10000000000000", + "1000000000000000", + "100000000000000000", + "10000000000000000000", + "1000000000000000000000", + "100000000000000000000000", + "10000000000000000000000000", + "1000000000000000000000000000", + "100000000000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000", + "100000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000000", + "100000000000000", + "100000000000000000", + "100000000000000000000", + "100000000000000000000000", + "100000000000000000000000000", + "100000000000000000000000000000", + "100000000000000000000000000000000", + "100000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000000", + "1000000000000000", + "10000000000000000000", + "100000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000000000", + "100000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000000000000000", + "100000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000000", + "1000000000000", + "10000000000000", + "100000000000000", + "1000000000000000", + "10000000000000000", + "100000000000000000", + "1000000000000000000", + "10000000000000000000", + "100000000000000000000", + "1000000000000000000000", + "10000000000000000000000", + "100000000000000000000000", + "1000000000000000000000000", + "10000000000000000000000000", + "100000000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000", + "1000000000000000000000000000000000", + "10000000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000000", + "10000000000000", + "1000000000000000", + "100000000000000000", + "10000000000000000000", + "1000000000000000000000", + "100000000000000000000000", + "10000000000000000000000000", + "1000000000000000000000000000", + "100000000000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000", + "100000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000000", + "100000000000000", + "100000000000000000", + "100000000000000000000", + "100000000000000000000000", + "100000000000000000000000000", + "100000000000000000000000000000", + "100000000000000000000000000000000", + "100000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000000", + "1000000000000000", + "10000000000000000000", + "100000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000000000", + "100000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000000000000000", + "100000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000000", + "1000000000000", + "10000000000000", + "100000000000000", + "1000000000000000", + "10000000000000000", + "100000000000000000", + "1000000000000000000", + "10000000000000000000", + "100000000000000000000", + "1000000000000000000000", + "10000000000000000000000", + "100000000000000000000000", + "1000000000000000000000000", + "10000000000000000000000000", + "100000000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000", + "1000000000000000000000000000000000", + "10000000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000000", + "10000000000000", + "1000000000000000", + "100000000000000000", + "10000000000000000000", + "1000000000000000000000", + "100000000000000000000000", + "10000000000000000000000000", + "1000000000000000000000000000", + "100000000000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000", + "100000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000000", + "100000000000000", + "100000000000000000", + "100000000000000000000", + "100000000000000000000000", + "100000000000000000000000000", + "100000000000000000000000000000", + "100000000000000000000000000000000", + "100000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000000", + "1000000000000000", + "10000000000000000000", + "100000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000000000", + "100000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000000000000000", + "100000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000000", + "1000000000000", + "10000000000000", + "100000000000000", + "1000000000000000", + "10000000000000000", + "100000000000000000", + "1000000000000000000", + "10000000000000000000", + "100000000000000000000", + "1000000000000000000000", + "10000000000000000000000", + "100000000000000000000000", + "1000000000000000000000000", + "10000000000000000000000000", + "100000000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000", + "1000000000000000000000000000000000", + "10000000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000000", + "10000000000000", + "1000000000000000", + "100000000000000000", + "10000000000000000000", + "1000000000000000000000", + "100000000000000000000000", + "10000000000000000000000000", + "1000000000000000000000000000", + "100000000000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000", + "100000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000000", + "100000000000000", + "100000000000000000", + "100000000000000000000", + "100000000000000000000000", + "100000000000000000000000000", + "100000000000000000000000000000", + "100000000000000000000000000000000", + "100000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000000", + "1000000000000000", + "10000000000000000000", + "100000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000000000", + "100000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000000000000000", + "100000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000000", + "1000000000000", + "10000000000000", + "100000000000000", + "1000000000000000", + "10000000000000000", + "100000000000000000", + "1000000000000000000", + "10000000000000000000", + "100000000000000000000", + "1000000000000000000000", + "10000000000000000000000", + "100000000000000000000000", + "1000000000000000000000000", + "10000000000000000000000000", + "100000000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000", + "1000000000000000000000000000000000", + "10000000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000000", + "10000000000000", + "1000000000000000", + "100000000000000000", + "10000000000000000000", + "1000000000000000000000", + "100000000000000000000000", + "10000000000000000000000000", + "1000000000000000000000000000", + "100000000000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000", + "100000000000000000000000000000000000", + "10000000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000000", + "100000000000000", + "100000000000000000", + "100000000000000000000", + "100000000000000000000000", + "100000000000000000000000000", + "100000000000000000000000000000", + "100000000000000000000000000000000", + "100000000000000000000000000000000000", + "100000000000000000000000000000000000000", + "100000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000000", + "1000000000000000", + "10000000000000000000", + "100000000000000000000000", + "1000000000000000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000000000", + "100000000000000000000000", + "10000000000000000000000000000000", + "1000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000000000000", + "100000000000000000000000000000", + "1000000000000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000", + "100000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000000000000000", + "100000000000000000000000000000000", + "10000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000", + "10000000000000000000000000000000", + "100000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000", + "10000000000000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = 0.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000000000000000000000000000000000000000000000000000000000", + "10000000000000000000000000000000", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 1, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0", + "01", + "010", + "0100", + "01000", + "010000", + "0100000", + "01000000", + "010000001", + "0100000010", + "01000000100", + "010000001000", + "0100000010000", + "01000000100000", + "010000001000001", + "0100000010000011", + "01000000100000110", + "010000001000001101", + "0100000010000011010", + "01000000100000110101", + "010000001000001101010", + "0100000010000011010100", + "01000000100000110101001", + "010000001000001101010011", + "0100000010000011010100111", + "01000000100000110101001111", + "010000001000001101010011111", + "0100000010000011010100111111", + "01000000100000110101001111110", + "010000001000001101010011111101", + "0100000010000011010100111111011", + "01000000100000110101001111110111", + "010000001000001101010011111101111", + "0100000010000011010100111111011111", + "01000000100000110101001111110111110", + "010000001000001101010011111101111100", + "0100000010000011010100111111011111001", + "01000000100000110101001111110111110011", + "010000001000001101010011111101111100111", + "0100000010000011010100111111011111001110", + "01000000100000110101001111110111110011101", + "010000001000001101010011111101111100111011", + "0100000010000011010100111111011111001110110", + "01000000100000110101001111110111110011101101", + "010000001000001101010011111101111100111011011", + "0100000010000011010100111111011111001110110110", + "01000000100000110101001111110111110011101101100", + "010000001000001101010011111101111100111011011001", + "0100000010000011010100111111011111001110110110010", + "01000000100000110101001111110111110011101101100100", + "010000001000001101010011111101111100111011011001000", + "0100000010000011010100111111011111001110110110010001", + "01000000100000110101001111110111110011101101100100010", + "010000001000001101010011111101111100111011011001000101", + "0100000010000011010100111111011111001110110110010001011", + "01000000100000110101001111110111110011101101100100010110", + "010000001000001101010011111101111100111011011001000101101", + "0100000010000011010100111111011111001110110110010001011010", + "01000000100000110101001111110111110011101101100100010110100", + "010000001000001101010011111101111100111011011001000101101000", + "0100000010000011010100111111011111001110110110010001011010000", + "01000000100000110101001111110111110011101101100100010110100001", + "010000001000001101010011111101111100111011011001000101101000011", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 2, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01", + "0100", + "010000", + "01000000", + "0100000010", + "010000001000", + "01000000100000", + "0100000010000011", + "010000001000001101", + "01000000100000110101", + "0100000010000011010100", + "010000001000001101010011", + "01000000100000110101001111", + "0100000010000011010100111111", + "010000001000001101010011111101", + "01000000100000110101001111110111", + "0100000010000011010100111111011111", + "010000001000001101010011111101111100", + "01000000100000110101001111110111110011", + "0100000010000011010100111111011111001110", + "010000001000001101010011111101111100111011", + "01000000100000110101001111110111110011101101", + "0100000010000011010100111111011111001110110110", + "010000001000001101010011111101111100111011011001", + "01000000100000110101001111110111110011101101100100", + "0100000010000011010100111111011111001110110110010001", + "010000001000001101010011111101111100111011011001000101", + "01000000100000110101001111110111110011101101100100010110", + "0100000010000011010100111111011111001110110110010001011010", + "010000001000001101010011111101111100111011011001000101101000", + "01000000100000110101001111110111110011101101100100010110100001", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 3, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "010", + "010000", + "010000001", + "010000001000", + "010000001000001", + "010000001000001101", + "010000001000001101010", + "010000001000001101010011", + "010000001000001101010011111", + "010000001000001101010011111101", + "010000001000001101010011111101111", + "010000001000001101010011111101111100", + "010000001000001101010011111101111100111", + "010000001000001101010011111101111100111011", + "010000001000001101010011111101111100111011011", + "010000001000001101010011111101111100111011011001", + "010000001000001101010011111101111100111011011001000", + "010000001000001101010011111101111100111011011001000101", + "010000001000001101010011111101111100111011011001000101101", + "010000001000001101010011111101111100111011011001000101101000", + "010000001000001101010011111101111100111011011001000101101000011", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 4, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100", + "01000000", + "010000001000", + "0100000010000011", + "01000000100000110101", + "010000001000001101010011", + "0100000010000011010100111111", + "01000000100000110101001111110111", + "010000001000001101010011111101111100", + "0100000010000011010100111111011111001110", + "01000000100000110101001111110111110011101101", + "010000001000001101010011111101111100111011011001", + "0100000010000011010100111111011111001110110110010001", + "01000000100000110101001111110111110011101101100100010110", + "010000001000001101010011111101111100111011011001000101101000", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 8, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01000000", + "0100000010000011", + "010000001000001101010011", + "01000000100000110101001111110111", + "0100000010000011010100111111011111001110", + "010000001000001101010011111101111100111011011001", + "01000000100000110101001111110111110011101101100100010110", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 10, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100000010", + "01000000100000110101", + "010000001000001101010011111101", + "0100000010000011010100111111011111001110", + "01000000100000110101001111110111110011101101100100", + "010000001000001101010011111101111100111011011001000101101000", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 11, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01000000100", + "0100000010000011010100", + "010000001000001101010011111101111", + "01000000100000110101001111110111110011101101", + "0100000010000011010100111111011111001110110110010001011", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 16, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100000010000011", + "01000000100000110101001111110111", + "010000001000001101010011111101111100111011011001", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 31, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100000010000011010100111111011", + "01000000100000110101001111110111110011101101100100010110100001", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 32, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01000000100000110101001111110111", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0", + "01", + "010", + "0100", + "01000", + "010000", + "0100000", + "01000000", + "010000001", + "0100000010", + "01000000100", + "010000001000", + "0100000010000", + "01000000100000", + "010000001000001", + "0100000010000011", + "01000000100000110", + "010000001000001101", + "0100000010000011010", + "01000000100000110101", + "010000001000001101010", + "0100000010000011010100", + "01000000100000110101001", + "010000001000001101010011", + "0100000010000011010100111", + "01000000100000110101001111", + "010000001000001101010011111", + "0100000010000011010100111111", + "01000000100000110101001111110", + "010000001000001101010011111101", + "0100000010000011010100111111011", + "01000000100000110101001111110111", + "010000001000001101010011111101111", + "0100000010000011010100111111011111", + "01000000100000110101001111110111110", + "010000001000001101010011111101111100", + "0100000010000011010100111111011111001", + "01000000100000110101001111110111110011", + "010000001000001101010011111101111100111", + "0100000010000011010100111111011111001110", + "01000000100000110101001111110111110011101", + "010000001000001101010011111101111100111011", + "0100000010000011010100111111011111001110110", + "01000000100000110101001111110111110011101101", + "010000001000001101010011111101111100111011011", + "0100000010000011010100111111011111001110110110", + "01000000100000110101001111110111110011101101100", + "010000001000001101010011111101111100111011011001", + "0100000010000011010100111111011111001110110110010", + "01000000100000110101001111110111110011101101100100", + "010000001000001101010011111101111100111011011001000", + "0100000010000011010100111111011111001110110110010001", + "01000000100000110101001111110111110011101101100100010", + "010000001000001101010011111101111100111011011001000101", + "0100000010000011010100111111011111001110110110010001011", + "01000000100000110101001111110111110011101101100100010110", + "010000001000001101010011111101111100111011011001000101101", + "0100000010000011010100111111011111001110110110010001011010", + "01000000100000110101001111110111110011101101100100010110100", + "010000001000001101010011111101111100111011011001000101101000", + "0100000010000011010100111111011111001110110110010001011010000", + "01000000100000110101001111110111110011101101100100010110100001", + "010000001000001101010011111101111100111011011001000101101000011", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01", + "0100", + "010000", + "01000000", + "0100000010", + "010000001000", + "01000000100000", + "0100000010000011", + "010000001000001101", + "01000000100000110101", + "0100000010000011010100", + "010000001000001101010011", + "01000000100000110101001111", + "0100000010000011010100111111", + "010000001000001101010011111101", + "01000000100000110101001111110111", + "0100000010000011010100111111011111", + "010000001000001101010011111101111100", + "01000000100000110101001111110111110011", + "0100000010000011010100111111011111001110", + "010000001000001101010011111101111100111011", + "01000000100000110101001111110111110011101101", + "0100000010000011010100111111011111001110110110", + "010000001000001101010011111101111100111011011001", + "01000000100000110101001111110111110011101101100100", + "0100000010000011010100111111011111001110110110010001", + "010000001000001101010011111101111100111011011001000101", + "01000000100000110101001111110111110011101101100100010110", + "0100000010000011010100111111011111001110110110010001011010", + "010000001000001101010011111101111100111011011001000101101000", + "01000000100000110101001111110111110011101101100100010110100001", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "010", + "010000", + "010000001", + "010000001000", + "010000001000001", + "010000001000001101", + "010000001000001101010", + "010000001000001101010011", + "010000001000001101010011111", + "010000001000001101010011111101", + "010000001000001101010011111101111", + "010000001000001101010011111101111100", + "010000001000001101010011111101111100111", + "010000001000001101010011111101111100111011", + "010000001000001101010011111101111100111011011", + "010000001000001101010011111101111100111011011001", + "010000001000001101010011111101111100111011011001000", + "010000001000001101010011111101111100111011011001000101", + "010000001000001101010011111101111100111011011001000101101", + "010000001000001101010011111101111100111011011001000101101000", + "010000001000001101010011111101111100111011011001000101101000011", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100", + "01000000", + "010000001000", + "0100000010000011", + "01000000100000110101", + "010000001000001101010011", + "0100000010000011010100111111", + "01000000100000110101001111110111", + "010000001000001101010011111101111100", + "0100000010000011010100111111011111001110", + "01000000100000110101001111110111110011101101", + "010000001000001101010011111101111100111011011001", + "0100000010000011010100111111011111001110110110010001", + "01000000100000110101001111110111110011101101100100010110", + "010000001000001101010011111101111100111011011001000101101000", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01000000", + "0100000010000011", + "010000001000001101010011", + "01000000100000110101001111110111", + "0100000010000011010100111111011111001110", + "010000001000001101010011111101111100111011011001", + "01000000100000110101001111110111110011101101100100010110", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100000010", + "01000000100000110101", + "010000001000001101010011111101", + "0100000010000011010100111111011111001110", + "01000000100000110101001111110111110011101101100100", + "010000001000001101010011111101111100111011011001000101101000", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01000000100", + "0100000010000011010100", + "010000001000001101010011111101111", + "01000000100000110101001111110111110011101101", + "0100000010000011010100111111011111001110110110010001011", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100000010000011", + "01000000100000110101001111110111", + "010000001000001101010011111101111100111011011001", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100000010000011010100111111011", + "01000000100000110101001111110111110011101101100100010110100001", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01000000100000110101001111110111", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0", + "01", + "010", + "0100", + "01000", + "010000", + "0100000", + "01000000", + "010000001", + "0100000010", + "01000000100", + "010000001000", + "0100000010000", + "01000000100000", + "010000001000001", + "0100000010000011", + "01000000100000110", + "010000001000001101", + "0100000010000011010", + "01000000100000110101", + "010000001000001101010", + "0100000010000011010100", + "01000000100000110101001", + "010000001000001101010011", + "0100000010000011010100111", + "01000000100000110101001111", + "010000001000001101010011111", + "0100000010000011010100111111", + "01000000100000110101001111110", + "010000001000001101010011111101", + "0100000010000011010100111111011", + "01000000100000110101001111110111", + "010000001000001101010011111101111", + "0100000010000011010100111111011111", + "01000000100000110101001111110111110", + "010000001000001101010011111101111100", + "0100000010000011010100111111011111001", + "01000000100000110101001111110111110011", + "010000001000001101010011111101111100111", + "0100000010000011010100111111011111001110", + "01000000100000110101001111110111110011101", + "010000001000001101010011111101111100111011", + "0100000010000011010100111111011111001110110", + "01000000100000110101001111110111110011101101", + "010000001000001101010011111101111100111011011", + "0100000010000011010100111111011111001110110110", + "01000000100000110101001111110111110011101101100", + "010000001000001101010011111101111100111011011001", + "0100000010000011010100111111011111001110110110010", + "01000000100000110101001111110111110011101101100100", + "010000001000001101010011111101111100111011011001000", + "0100000010000011010100111111011111001110110110010001", + "01000000100000110101001111110111110011101101100100010", + "010000001000001101010011111101111100111011011001000101", + "0100000010000011010100111111011111001110110110010001011", + "01000000100000110101001111110111110011101101100100010110", + "010000001000001101010011111101111100111011011001000101101", + "0100000010000011010100111111011111001110110110010001011010", + "01000000100000110101001111110111110011101101100100010110100", + "010000001000001101010011111101111100111011011001000101101000", + "0100000010000011010100111111011111001110110110010001011010000", + "01000000100000110101001111110111110011101101100100010110100001", + "010000001000001101010011111101111100111011011001000101101000011", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01", + "0100", + "010000", + "01000000", + "0100000010", + "010000001000", + "01000000100000", + "0100000010000011", + "010000001000001101", + "01000000100000110101", + "0100000010000011010100", + "010000001000001101010011", + "01000000100000110101001111", + "0100000010000011010100111111", + "010000001000001101010011111101", + "01000000100000110101001111110111", + "0100000010000011010100111111011111", + "010000001000001101010011111101111100", + "01000000100000110101001111110111110011", + "0100000010000011010100111111011111001110", + "010000001000001101010011111101111100111011", + "01000000100000110101001111110111110011101101", + "0100000010000011010100111111011111001110110110", + "010000001000001101010011111101111100111011011001", + "01000000100000110101001111110111110011101101100100", + "0100000010000011010100111111011111001110110110010001", + "010000001000001101010011111101111100111011011001000101", + "01000000100000110101001111110111110011101101100100010110", + "0100000010000011010100111111011111001110110110010001011010", + "010000001000001101010011111101111100111011011001000101101000", + "01000000100000110101001111110111110011101101100100010110100001", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "010", + "010000", + "010000001", + "010000001000", + "010000001000001", + "010000001000001101", + "010000001000001101010", + "010000001000001101010011", + "010000001000001101010011111", + "010000001000001101010011111101", + "010000001000001101010011111101111", + "010000001000001101010011111101111100", + "010000001000001101010011111101111100111", + "010000001000001101010011111101111100111011", + "010000001000001101010011111101111100111011011", + "010000001000001101010011111101111100111011011001", + "010000001000001101010011111101111100111011011001000", + "010000001000001101010011111101111100111011011001000101", + "010000001000001101010011111101111100111011011001000101101", + "010000001000001101010011111101111100111011011001000101101000", + "010000001000001101010011111101111100111011011001000101101000011", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100", + "01000000", + "010000001000", + "0100000010000011", + "01000000100000110101", + "010000001000001101010011", + "0100000010000011010100111111", + "01000000100000110101001111110111", + "010000001000001101010011111101111100", + "0100000010000011010100111111011111001110", + "01000000100000110101001111110111110011101101", + "010000001000001101010011111101111100111011011001", + "0100000010000011010100111111011111001110110110010001", + "01000000100000110101001111110111110011101101100100010110", + "010000001000001101010011111101111100111011011001000101101000", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01000000", + "0100000010000011", + "010000001000001101010011", + "01000000100000110101001111110111", + "0100000010000011010100111111011111001110", + "010000001000001101010011111101111100111011011001", + "01000000100000110101001111110111110011101101100100010110", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100000010", + "01000000100000110101", + "010000001000001101010011111101", + "0100000010000011010100111111011111001110", + "01000000100000110101001111110111110011101101100100", + "010000001000001101010011111101111100111011011001000101101000", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01000000100", + "0100000010000011010100", + "010000001000001101010011111101111", + "01000000100000110101001111110111110011101101", + "0100000010000011010100111111011111001110110110010001011", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100000010000011", + "01000000100000110101001111110111", + "010000001000001101010011111101111100111011011001", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "0100000010000011010100111111011", + "01000000100000110101001111110111110011101101100100010110100001", + }, +}, +{ + .value = -0.00700000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "0100000010000011010100111111011111001110110110010001011010000111", + "01000000100000110101001111110111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1", + "11", + "110", + "1100", + "11000", + "110000", + "1100000", + "11000000", + "110000000", + "1100000001", + "11000000010", + "110000000100", + "1100000001000", + "11000000010000", + "110000000100000", + "1100000001000000", + "11000000010000000", + "110000000100000001", + "1100000001000000011", + "11000000010000000110", + "110000000100000001100", + "1100000001000000011000", + "11000000010000000110001", + "110000000100000001100011", + "1100000001000000011000110", + "11000000010000000110001101", + "110000000100000001100011011", + "1100000001000000011000110111", + "11000000010000000110001101110", + "110000000100000001100011011101", + "1100000001000000011000110111010", + "11000000010000000110001101110100", + "110000000100000001100011011101001", + "1100000001000000011000110111010010", + "11000000010000000110001101110100101", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111", + "11000000010000000110001101110100101111", + "110000000100000001100011011101001011110", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000", + "110000000100000001100011011101001011110001", + "1100000001000000011000110111010010111100011", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101", + "1100000001000000011000110111010010111100011010", + "11000000010000000110001101110100101111000110101", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111", + "110000000100000001100011011101001011110001101010011111", + "1100000001000000011000110111010010111100011010100111111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101", + "1100000001000000011000110111010010111100011010100111111011", + "11000000010000000110001101110100101111000110101001111110111", + "110000000100000001100011011101001011110001101010011111101111", + "1100000001000000011000110111010010111100011010100111111011111", + "11000000010000000110001101110100101111000110101001111110111110", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11", + "1100", + "110000", + "11000000", + "1100000001", + "110000000100", + "11000000010000", + "1100000001000000", + "110000000100000001", + "11000000010000000110", + "1100000001000000011000", + "110000000100000001100011", + "11000000010000000110001101", + "1100000001000000011000110111", + "110000000100000001100011011101", + "11000000010000000110001101110100", + "1100000001000000011000110111010010", + "110000000100000001100011011101001011", + "11000000010000000110001101110100101111", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001", + "1100000001000000011000110111010010111100011010100111", + "110000000100000001100011011101001011110001101010011111", + "11000000010000000110001101110100101111000110101001111110", + "1100000001000000011000110111010010111100011010100111111011", + "110000000100000001100011011101001011110001101010011111101111", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "110", + "110000", + "110000000", + "110000000100", + "110000000100000", + "110000000100000001", + "110000000100000001100", + "110000000100000001100011", + "110000000100000001100011011", + "110000000100000001100011011101", + "110000000100000001100011011101001", + "110000000100000001100011011101001011", + "110000000100000001100011011101001011110", + "110000000100000001100011011101001011110001", + "110000000100000001100011011101001011110001101", + "110000000100000001100011011101001011110001101010", + "110000000100000001100011011101001011110001101010011", + "110000000100000001100011011101001011110001101010011111", + "110000000100000001100011011101001011110001101010011111101", + "110000000100000001100011011101001011110001101010011111101111", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100", + "11000000", + "110000000100", + "1100000001000000", + "11000000010000000110", + "110000000100000001100011", + "1100000001000000011000110111", + "11000000010000000110001101110100", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000", + "1100000001000000", + "110000000100000001100011", + "11000000010000000110001101110100", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001", + "11000000010000000110", + "110000000100000001100011011101", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010", + "1100000001000000011000", + "110000000100000001100011011101001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010100111111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000", + "11000000010000000110001101110100", + "110000000100000001100011011101001011110001101010", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000011000110111010", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010000000110001101110100", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1", + "11", + "110", + "1100", + "11000", + "110000", + "1100000", + "11000000", + "110000000", + "1100000001", + "11000000010", + "110000000100", + "1100000001000", + "11000000010000", + "110000000100000", + "1100000001000000", + "11000000010000000", + "110000000100000001", + "1100000001000000011", + "11000000010000000110", + "110000000100000001100", + "1100000001000000011000", + "11000000010000000110001", + "110000000100000001100011", + "1100000001000000011000110", + "11000000010000000110001101", + "110000000100000001100011011", + "1100000001000000011000110111", + "11000000010000000110001101110", + "110000000100000001100011011101", + "1100000001000000011000110111010", + "11000000010000000110001101110100", + "110000000100000001100011011101001", + "1100000001000000011000110111010010", + "11000000010000000110001101110100101", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111", + "11000000010000000110001101110100101111", + "110000000100000001100011011101001011110", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000", + "110000000100000001100011011101001011110001", + "1100000001000000011000110111010010111100011", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101", + "1100000001000000011000110111010010111100011010", + "11000000010000000110001101110100101111000110101", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111", + "110000000100000001100011011101001011110001101010011111", + "1100000001000000011000110111010010111100011010100111111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101", + "1100000001000000011000110111010010111100011010100111111011", + "11000000010000000110001101110100101111000110101001111110111", + "110000000100000001100011011101001011110001101010011111101111", + "1100000001000000011000110111010010111100011010100111111011111", + "11000000010000000110001101110100101111000110101001111110111110", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11", + "1100", + "110000", + "11000000", + "1100000001", + "110000000100", + "11000000010000", + "1100000001000000", + "110000000100000001", + "11000000010000000110", + "1100000001000000011000", + "110000000100000001100011", + "11000000010000000110001101", + "1100000001000000011000110111", + "110000000100000001100011011101", + "11000000010000000110001101110100", + "1100000001000000011000110111010010", + "110000000100000001100011011101001011", + "11000000010000000110001101110100101111", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001", + "1100000001000000011000110111010010111100011010100111", + "110000000100000001100011011101001011110001101010011111", + "11000000010000000110001101110100101111000110101001111110", + "1100000001000000011000110111010010111100011010100111111011", + "110000000100000001100011011101001011110001101010011111101111", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "110", + "110000", + "110000000", + "110000000100", + "110000000100000", + "110000000100000001", + "110000000100000001100", + "110000000100000001100011", + "110000000100000001100011011", + "110000000100000001100011011101", + "110000000100000001100011011101001", + "110000000100000001100011011101001011", + "110000000100000001100011011101001011110", + "110000000100000001100011011101001011110001", + "110000000100000001100011011101001011110001101", + "110000000100000001100011011101001011110001101010", + "110000000100000001100011011101001011110001101010011", + "110000000100000001100011011101001011110001101010011111", + "110000000100000001100011011101001011110001101010011111101", + "110000000100000001100011011101001011110001101010011111101111", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100", + "11000000", + "110000000100", + "1100000001000000", + "11000000010000000110", + "110000000100000001100011", + "1100000001000000011000110111", + "11000000010000000110001101110100", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000", + "1100000001000000", + "110000000100000001100011", + "11000000010000000110001101110100", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001", + "11000000010000000110", + "110000000100000001100011011101", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010", + "1100000001000000011000", + "110000000100000001100011011101001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010100111111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000", + "11000000010000000110001101110100", + "110000000100000001100011011101001011110001101010", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000011000110111010", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010000000110001101110100", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1", + "11", + "110", + "1100", + "11000", + "110000", + "1100000", + "11000000", + "110000000", + "1100000001", + "11000000010", + "110000000100", + "1100000001000", + "11000000010000", + "110000000100000", + "1100000001000000", + "11000000010000000", + "110000000100000001", + "1100000001000000011", + "11000000010000000110", + "110000000100000001100", + "1100000001000000011000", + "11000000010000000110001", + "110000000100000001100011", + "1100000001000000011000110", + "11000000010000000110001101", + "110000000100000001100011011", + "1100000001000000011000110111", + "11000000010000000110001101110", + "110000000100000001100011011101", + "1100000001000000011000110111010", + "11000000010000000110001101110100", + "110000000100000001100011011101001", + "1100000001000000011000110111010010", + "11000000010000000110001101110100101", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111", + "11000000010000000110001101110100101111", + "110000000100000001100011011101001011110", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000", + "110000000100000001100011011101001011110001", + "1100000001000000011000110111010010111100011", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101", + "1100000001000000011000110111010010111100011010", + "11000000010000000110001101110100101111000110101", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111", + "110000000100000001100011011101001011110001101010011111", + "1100000001000000011000110111010010111100011010100111111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101", + "1100000001000000011000110111010010111100011010100111111011", + "11000000010000000110001101110100101111000110101001111110111", + "110000000100000001100011011101001011110001101010011111101111", + "1100000001000000011000110111010010111100011010100111111011111", + "11000000010000000110001101110100101111000110101001111110111110", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11", + "1100", + "110000", + "11000000", + "1100000001", + "110000000100", + "11000000010000", + "1100000001000000", + "110000000100000001", + "11000000010000000110", + "1100000001000000011000", + "110000000100000001100011", + "11000000010000000110001101", + "1100000001000000011000110111", + "110000000100000001100011011101", + "11000000010000000110001101110100", + "1100000001000000011000110111010010", + "110000000100000001100011011101001011", + "11000000010000000110001101110100101111", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001", + "1100000001000000011000110111010010111100011010100111", + "110000000100000001100011011101001011110001101010011111", + "11000000010000000110001101110100101111000110101001111110", + "1100000001000000011000110111010010111100011010100111111011", + "110000000100000001100011011101001011110001101010011111101111", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "110", + "110000", + "110000000", + "110000000100", + "110000000100000", + "110000000100000001", + "110000000100000001100", + "110000000100000001100011", + "110000000100000001100011011", + "110000000100000001100011011101", + "110000000100000001100011011101001", + "110000000100000001100011011101001011", + "110000000100000001100011011101001011110", + "110000000100000001100011011101001011110001", + "110000000100000001100011011101001011110001101", + "110000000100000001100011011101001011110001101010", + "110000000100000001100011011101001011110001101010011", + "110000000100000001100011011101001011110001101010011111", + "110000000100000001100011011101001011110001101010011111101", + "110000000100000001100011011101001011110001101010011111101111", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100", + "11000000", + "110000000100", + "1100000001000000", + "11000000010000000110", + "110000000100000001100011", + "1100000001000000011000110111", + "11000000010000000110001101110100", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000", + "1100000001000000", + "110000000100000001100011", + "11000000010000000110001101110100", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001", + "11000000010000000110", + "110000000100000001100011011101", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010", + "1100000001000000011000", + "110000000100000001100011011101001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010100111111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000", + "11000000010000000110001101110100", + "110000000100000001100011011101001011110001101010", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000011000110111010", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010000000110001101110100", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1", + "11", + "110", + "1100", + "11000", + "110000", + "1100000", + "11000000", + "110000000", + "1100000001", + "11000000010", + "110000000100", + "1100000001000", + "11000000010000", + "110000000100000", + "1100000001000000", + "11000000010000000", + "110000000100000001", + "1100000001000000011", + "11000000010000000110", + "110000000100000001100", + "1100000001000000011000", + "11000000010000000110001", + "110000000100000001100011", + "1100000001000000011000110", + "11000000010000000110001101", + "110000000100000001100011011", + "1100000001000000011000110111", + "11000000010000000110001101110", + "110000000100000001100011011101", + "1100000001000000011000110111010", + "11000000010000000110001101110100", + "110000000100000001100011011101001", + "1100000001000000011000110111010010", + "11000000010000000110001101110100101", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111", + "11000000010000000110001101110100101111", + "110000000100000001100011011101001011110", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000", + "110000000100000001100011011101001011110001", + "1100000001000000011000110111010010111100011", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101", + "1100000001000000011000110111010010111100011010", + "11000000010000000110001101110100101111000110101", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111", + "110000000100000001100011011101001011110001101010011111", + "1100000001000000011000110111010010111100011010100111111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101", + "1100000001000000011000110111010010111100011010100111111011", + "11000000010000000110001101110100101111000110101001111110111", + "110000000100000001100011011101001011110001101010011111101111", + "1100000001000000011000110111010010111100011010100111111011111", + "11000000010000000110001101110100101111000110101001111110111110", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11", + "1100", + "110000", + "11000000", + "1100000001", + "110000000100", + "11000000010000", + "1100000001000000", + "110000000100000001", + "11000000010000000110", + "1100000001000000011000", + "110000000100000001100011", + "11000000010000000110001101", + "1100000001000000011000110111", + "110000000100000001100011011101", + "11000000010000000110001101110100", + "1100000001000000011000110111010010", + "110000000100000001100011011101001011", + "11000000010000000110001101110100101111", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001", + "1100000001000000011000110111010010111100011010100111", + "110000000100000001100011011101001011110001101010011111", + "11000000010000000110001101110100101111000110101001111110", + "1100000001000000011000110111010010111100011010100111111011", + "110000000100000001100011011101001011110001101010011111101111", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "110", + "110000", + "110000000", + "110000000100", + "110000000100000", + "110000000100000001", + "110000000100000001100", + "110000000100000001100011", + "110000000100000001100011011", + "110000000100000001100011011101", + "110000000100000001100011011101001", + "110000000100000001100011011101001011", + "110000000100000001100011011101001011110", + "110000000100000001100011011101001011110001", + "110000000100000001100011011101001011110001101", + "110000000100000001100011011101001011110001101010", + "110000000100000001100011011101001011110001101010011", + "110000000100000001100011011101001011110001101010011111", + "110000000100000001100011011101001011110001101010011111101", + "110000000100000001100011011101001011110001101010011111101111", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100", + "11000000", + "110000000100", + "1100000001000000", + "11000000010000000110", + "110000000100000001100011", + "1100000001000000011000110111", + "11000000010000000110001101110100", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000", + "1100000001000000", + "110000000100000001100011", + "11000000010000000110001101110100", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001", + "11000000010000000110", + "110000000100000001100011011101", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010", + "1100000001000000011000", + "110000000100000001100011011101001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010100111111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000", + "11000000010000000110001101110100", + "110000000100000001100011011101001011110001101010", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000011000110111010", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010000000110001101110100", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1", + "11", + "110", + "1100", + "11000", + "110000", + "1100000", + "11000000", + "110000000", + "1100000001", + "11000000010", + "110000000100", + "1100000001000", + "11000000010000", + "110000000100000", + "1100000001000000", + "11000000010000000", + "110000000100000001", + "1100000001000000011", + "11000000010000000110", + "110000000100000001100", + "1100000001000000011000", + "11000000010000000110001", + "110000000100000001100011", + "1100000001000000011000110", + "11000000010000000110001101", + "110000000100000001100011011", + "1100000001000000011000110111", + "11000000010000000110001101110", + "110000000100000001100011011101", + "1100000001000000011000110111010", + "11000000010000000110001101110100", + "110000000100000001100011011101001", + "1100000001000000011000110111010010", + "11000000010000000110001101110100101", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111", + "11000000010000000110001101110100101111", + "110000000100000001100011011101001011110", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000", + "110000000100000001100011011101001011110001", + "1100000001000000011000110111010010111100011", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101", + "1100000001000000011000110111010010111100011010", + "11000000010000000110001101110100101111000110101", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111", + "110000000100000001100011011101001011110001101010011111", + "1100000001000000011000110111010010111100011010100111111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101", + "1100000001000000011000110111010010111100011010100111111011", + "11000000010000000110001101110100101111000110101001111110111", + "110000000100000001100011011101001011110001101010011111101111", + "1100000001000000011000110111010010111100011010100111111011111", + "11000000010000000110001101110100101111000110101001111110111110", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11", + "1100", + "110000", + "11000000", + "1100000001", + "110000000100", + "11000000010000", + "1100000001000000", + "110000000100000001", + "11000000010000000110", + "1100000001000000011000", + "110000000100000001100011", + "11000000010000000110001101", + "1100000001000000011000110111", + "110000000100000001100011011101", + "11000000010000000110001101110100", + "1100000001000000011000110111010010", + "110000000100000001100011011101001011", + "11000000010000000110001101110100101111", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001", + "1100000001000000011000110111010010111100011010100111", + "110000000100000001100011011101001011110001101010011111", + "11000000010000000110001101110100101111000110101001111110", + "1100000001000000011000110111010010111100011010100111111011", + "110000000100000001100011011101001011110001101010011111101111", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "110", + "110000", + "110000000", + "110000000100", + "110000000100000", + "110000000100000001", + "110000000100000001100", + "110000000100000001100011", + "110000000100000001100011011", + "110000000100000001100011011101", + "110000000100000001100011011101001", + "110000000100000001100011011101001011", + "110000000100000001100011011101001011110", + "110000000100000001100011011101001011110001", + "110000000100000001100011011101001011110001101", + "110000000100000001100011011101001011110001101010", + "110000000100000001100011011101001011110001101010011", + "110000000100000001100011011101001011110001101010011111", + "110000000100000001100011011101001011110001101010011111101", + "110000000100000001100011011101001011110001101010011111101111", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100", + "11000000", + "110000000100", + "1100000001000000", + "11000000010000000110", + "110000000100000001100011", + "1100000001000000011000110111", + "11000000010000000110001101110100", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000", + "1100000001000000", + "110000000100000001100011", + "11000000010000000110001101110100", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001", + "11000000010000000110", + "110000000100000001100011011101", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010", + "1100000001000000011000", + "110000000100000001100011011101001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010100111111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000", + "11000000010000000110001101110100", + "110000000100000001100011011101001011110001101010", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000011000110111010", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010000000110001101110100", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1", + "11", + "110", + "1100", + "11000", + "110000", + "1100000", + "11000000", + "110000000", + "1100000001", + "11000000010", + "110000000100", + "1100000001000", + "11000000010000", + "110000000100000", + "1100000001000000", + "11000000010000000", + "110000000100000001", + "1100000001000000011", + "11000000010000000110", + "110000000100000001100", + "1100000001000000011000", + "11000000010000000110001", + "110000000100000001100011", + "1100000001000000011000110", + "11000000010000000110001101", + "110000000100000001100011011", + "1100000001000000011000110111", + "11000000010000000110001101110", + "110000000100000001100011011101", + "1100000001000000011000110111010", + "11000000010000000110001101110100", + "110000000100000001100011011101001", + "1100000001000000011000110111010010", + "11000000010000000110001101110100101", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111", + "11000000010000000110001101110100101111", + "110000000100000001100011011101001011110", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000", + "110000000100000001100011011101001011110001", + "1100000001000000011000110111010010111100011", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101", + "1100000001000000011000110111010010111100011010", + "11000000010000000110001101110100101111000110101", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111", + "110000000100000001100011011101001011110001101010011111", + "1100000001000000011000110111010010111100011010100111111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101", + "1100000001000000011000110111010010111100011010100111111011", + "11000000010000000110001101110100101111000110101001111110111", + "110000000100000001100011011101001011110001101010011111101111", + "1100000001000000011000110111010010111100011010100111111011111", + "11000000010000000110001101110100101111000110101001111110111110", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11", + "1100", + "110000", + "11000000", + "1100000001", + "110000000100", + "11000000010000", + "1100000001000000", + "110000000100000001", + "11000000010000000110", + "1100000001000000011000", + "110000000100000001100011", + "11000000010000000110001101", + "1100000001000000011000110111", + "110000000100000001100011011101", + "11000000010000000110001101110100", + "1100000001000000011000110111010010", + "110000000100000001100011011101001011", + "11000000010000000110001101110100101111", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001", + "1100000001000000011000110111010010111100011010100111", + "110000000100000001100011011101001011110001101010011111", + "11000000010000000110001101110100101111000110101001111110", + "1100000001000000011000110111010010111100011010100111111011", + "110000000100000001100011011101001011110001101010011111101111", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "110", + "110000", + "110000000", + "110000000100", + "110000000100000", + "110000000100000001", + "110000000100000001100", + "110000000100000001100011", + "110000000100000001100011011", + "110000000100000001100011011101", + "110000000100000001100011011101001", + "110000000100000001100011011101001011", + "110000000100000001100011011101001011110", + "110000000100000001100011011101001011110001", + "110000000100000001100011011101001011110001101", + "110000000100000001100011011101001011110001101010", + "110000000100000001100011011101001011110001101010011", + "110000000100000001100011011101001011110001101010011111", + "110000000100000001100011011101001011110001101010011111101", + "110000000100000001100011011101001011110001101010011111101111", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100", + "11000000", + "110000000100", + "1100000001000000", + "11000000010000000110", + "110000000100000001100011", + "1100000001000000011000110111", + "11000000010000000110001101110100", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000", + "1100000001000000", + "110000000100000001100011", + "11000000010000000110001101110100", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001", + "11000000010000000110", + "110000000100000001100011011101", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010", + "1100000001000000011000", + "110000000100000001100011011101001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010100111111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000", + "11000000010000000110001101110100", + "110000000100000001100011011101001011110001101010", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000011000110111010", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010000000110001101110100", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1", + "11", + "110", + "1100", + "11000", + "110000", + "1100000", + "11000000", + "110000000", + "1100000001", + "11000000010", + "110000000100", + "1100000001000", + "11000000010000", + "110000000100000", + "1100000001000000", + "11000000010000000", + "110000000100000001", + "1100000001000000011", + "11000000010000000110", + "110000000100000001100", + "1100000001000000011000", + "11000000010000000110001", + "110000000100000001100011", + "1100000001000000011000110", + "11000000010000000110001101", + "110000000100000001100011011", + "1100000001000000011000110111", + "11000000010000000110001101110", + "110000000100000001100011011101", + "1100000001000000011000110111010", + "11000000010000000110001101110100", + "110000000100000001100011011101001", + "1100000001000000011000110111010010", + "11000000010000000110001101110100101", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111", + "11000000010000000110001101110100101111", + "110000000100000001100011011101001011110", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000", + "110000000100000001100011011101001011110001", + "1100000001000000011000110111010010111100011", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101", + "1100000001000000011000110111010010111100011010", + "11000000010000000110001101110100101111000110101", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111", + "110000000100000001100011011101001011110001101010011111", + "1100000001000000011000110111010010111100011010100111111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101", + "1100000001000000011000110111010010111100011010100111111011", + "11000000010000000110001101110100101111000110101001111110111", + "110000000100000001100011011101001011110001101010011111101111", + "1100000001000000011000110111010010111100011010100111111011111", + "11000000010000000110001101110100101111000110101001111110111110", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11", + "1100", + "110000", + "11000000", + "1100000001", + "110000000100", + "11000000010000", + "1100000001000000", + "110000000100000001", + "11000000010000000110", + "1100000001000000011000", + "110000000100000001100011", + "11000000010000000110001101", + "1100000001000000011000110111", + "110000000100000001100011011101", + "11000000010000000110001101110100", + "1100000001000000011000110111010010", + "110000000100000001100011011101001011", + "11000000010000000110001101110100101111", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001", + "1100000001000000011000110111010010111100011010100111", + "110000000100000001100011011101001011110001101010011111", + "11000000010000000110001101110100101111000110101001111110", + "1100000001000000011000110111010010111100011010100111111011", + "110000000100000001100011011101001011110001101010011111101111", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "110", + "110000", + "110000000", + "110000000100", + "110000000100000", + "110000000100000001", + "110000000100000001100", + "110000000100000001100011", + "110000000100000001100011011", + "110000000100000001100011011101", + "110000000100000001100011011101001", + "110000000100000001100011011101001011", + "110000000100000001100011011101001011110", + "110000000100000001100011011101001011110001", + "110000000100000001100011011101001011110001101", + "110000000100000001100011011101001011110001101010", + "110000000100000001100011011101001011110001101010011", + "110000000100000001100011011101001011110001101010011111", + "110000000100000001100011011101001011110001101010011111101", + "110000000100000001100011011101001011110001101010011111101111", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100", + "11000000", + "110000000100", + "1100000001000000", + "11000000010000000110", + "110000000100000001100011", + "1100000001000000011000110111", + "11000000010000000110001101110100", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000", + "1100000001000000", + "110000000100000001100011", + "11000000010000000110001101110100", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001", + "11000000010000000110", + "110000000100000001100011011101", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010", + "1100000001000000011000", + "110000000100000001100011011101001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010100111111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000", + "11000000010000000110001101110100", + "110000000100000001100011011101001011110001101010", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000011000110111010", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010000000110001101110100", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1", + "11", + "110", + "1100", + "11000", + "110000", + "1100000", + "11000000", + "110000000", + "1100000001", + "11000000010", + "110000000100", + "1100000001000", + "11000000010000", + "110000000100000", + "1100000001000000", + "11000000010000000", + "110000000100000001", + "1100000001000000011", + "11000000010000000110", + "110000000100000001100", + "1100000001000000011000", + "11000000010000000110001", + "110000000100000001100011", + "1100000001000000011000110", + "11000000010000000110001101", + "110000000100000001100011011", + "1100000001000000011000110111", + "11000000010000000110001101110", + "110000000100000001100011011101", + "1100000001000000011000110111010", + "11000000010000000110001101110100", + "110000000100000001100011011101001", + "1100000001000000011000110111010010", + "11000000010000000110001101110100101", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111", + "11000000010000000110001101110100101111", + "110000000100000001100011011101001011110", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000", + "110000000100000001100011011101001011110001", + "1100000001000000011000110111010010111100011", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101", + "1100000001000000011000110111010010111100011010", + "11000000010000000110001101110100101111000110101", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111", + "110000000100000001100011011101001011110001101010011111", + "1100000001000000011000110111010010111100011010100111111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101", + "1100000001000000011000110111010010111100011010100111111011", + "11000000010000000110001101110100101111000110101001111110111", + "110000000100000001100011011101001011110001101010011111101111", + "1100000001000000011000110111010010111100011010100111111011111", + "11000000010000000110001101110100101111000110101001111110111110", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11", + "1100", + "110000", + "11000000", + "1100000001", + "110000000100", + "11000000010000", + "1100000001000000", + "110000000100000001", + "11000000010000000110", + "1100000001000000011000", + "110000000100000001100011", + "11000000010000000110001101", + "1100000001000000011000110111", + "110000000100000001100011011101", + "11000000010000000110001101110100", + "1100000001000000011000110111010010", + "110000000100000001100011011101001011", + "11000000010000000110001101110100101111", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001", + "1100000001000000011000110111010010111100011010100111", + "110000000100000001100011011101001011110001101010011111", + "11000000010000000110001101110100101111000110101001111110", + "1100000001000000011000110111010010111100011010100111111011", + "110000000100000001100011011101001011110001101010011111101111", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "110", + "110000", + "110000000", + "110000000100", + "110000000100000", + "110000000100000001", + "110000000100000001100", + "110000000100000001100011", + "110000000100000001100011011", + "110000000100000001100011011101", + "110000000100000001100011011101001", + "110000000100000001100011011101001011", + "110000000100000001100011011101001011110", + "110000000100000001100011011101001011110001", + "110000000100000001100011011101001011110001101", + "110000000100000001100011011101001011110001101010", + "110000000100000001100011011101001011110001101010011", + "110000000100000001100011011101001011110001101010011111", + "110000000100000001100011011101001011110001101010011111101", + "110000000100000001100011011101001011110001101010011111101111", + "110000000100000001100011011101001011110001101010011111101111101", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100", + "11000000", + "110000000100", + "1100000001000000", + "11000000010000000110", + "110000000100000001100011", + "1100000001000000011000110111", + "11000000010000000110001101110100", + "110000000100000001100011011101001011", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110", + "110000000100000001100011011101001011110001101010", + "1100000001000000011000110111010010111100011010100111", + "11000000010000000110001101110100101111000110101001111110", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000", + "1100000001000000", + "110000000100000001100011", + "11000000010000000110001101110100", + "1100000001000000011000110111010010111100", + "110000000100000001100011011101001011110001101010", + "11000000010000000110001101110100101111000110101001111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001", + "11000000010000000110", + "110000000100000001100011011101", + "1100000001000000011000110111010010111100", + "11000000010000000110001101110100101111000110101001", + "110000000100000001100011011101001011110001101010011111101111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010", + "1100000001000000011000", + "110000000100000001100011011101001", + "11000000010000000110001101110100101111000110", + "1100000001000000011000110111010010111100011010100111111", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000", + "11000000010000000110001101110100", + "110000000100000001100011011101001011110001101010", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "1100000001000000011000110111010", + "11000000010000000110001101110100101111000110101001111110111110", + }, +}, +{ + .value = 32.77700000000000102, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1100000001000000011000110111010010111100011010100111111011111010", + "11000000010000000110001101110100", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1", + "11", + "111", + "1111", + "11111", + "111111", + "1111111", + "11111111", + "111111111", + "1111111111", + "11111111111", + "111111111110", + "1111111111101", + "11111111111011", + "111111111110111", + "1111111111101111", + "11111111111011111", + "111111111110111111", + "1111111111101111111", + "11111111111011111111", + "111111111110111111111", + "1111111111101111111111", + "11111111111011111111111", + "111111111110111111111111", + "1111111111101111111111111", + "11111111111011111111111111", + "111111111110111111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111", + "111111111110111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111", + "1111111111101111111111111111111111", + "11111111111011111111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111", + "11111111111011111111111111111111111111", + "111111111110111111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111", + "111111111110111111111111111111111111111111", + "1111111111101111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11", + "1111", + "111111", + "11111111", + "1111111111", + "111111111110", + "11111111111011", + "1111111111101111", + "111111111110111111", + "11111111111011111111", + "1111111111101111111111", + "111111111110111111111111", + "11111111111011111111111111", + "1111111111101111111111111111", + "111111111110111111111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111", + "111111111110111111111111111111111111", + "11111111111011111111111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "111", + "111111", + "111111111", + "111111111110", + "111111111110111", + "111111111110111111", + "111111111110111111111", + "111111111110111111111111", + "111111111110111111111111111", + "111111111110111111111111111111", + "111111111110111111111111111111111", + "111111111110111111111111111111111111", + "111111111110111111111111111111111111111", + "111111111110111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111", + "11111111", + "111111111110", + "1111111111101111", + "11111111111011111111", + "111111111110111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111", + "1111111111101111", + "111111111110111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111", + "11111111111011111111", + "111111111110111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111", + "1111111111101111111111", + "111111111110111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1", + "11", + "111", + "1111", + "11111", + "111111", + "1111111", + "11111111", + "111111111", + "1111111111", + "11111111111", + "111111111110", + "1111111111101", + "11111111111011", + "111111111110111", + "1111111111101111", + "11111111111011111", + "111111111110111111", + "1111111111101111111", + "11111111111011111111", + "111111111110111111111", + "1111111111101111111111", + "11111111111011111111111", + "111111111110111111111111", + "1111111111101111111111111", + "11111111111011111111111111", + "111111111110111111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111", + "111111111110111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111", + "1111111111101111111111111111111111", + "11111111111011111111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111", + "11111111111011111111111111111111111111", + "111111111110111111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111", + "111111111110111111111111111111111111111111", + "1111111111101111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11", + "1111", + "111111", + "11111111", + "1111111111", + "111111111110", + "11111111111011", + "1111111111101111", + "111111111110111111", + "11111111111011111111", + "1111111111101111111111", + "111111111110111111111111", + "11111111111011111111111111", + "1111111111101111111111111111", + "111111111110111111111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111", + "111111111110111111111111111111111111", + "11111111111011111111111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "111", + "111111", + "111111111", + "111111111110", + "111111111110111", + "111111111110111111", + "111111111110111111111", + "111111111110111111111111", + "111111111110111111111111111", + "111111111110111111111111111111", + "111111111110111111111111111111111", + "111111111110111111111111111111111111", + "111111111110111111111111111111111111111", + "111111111110111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111", + "11111111", + "111111111110", + "1111111111101111", + "11111111111011111111", + "111111111110111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111", + "1111111111101111", + "111111111110111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111", + "11111111111011111111", + "111111111110111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111", + "1111111111101111111111", + "111111111110111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = 0.12340000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1", + "11", + "111", + "1111", + "11111", + "111111", + "1111111", + "11111111", + "111111111", + "1111111111", + "11111111111", + "111111111110", + "1111111111101", + "11111111111011", + "111111111110111", + "1111111111101111", + "11111111111011111", + "111111111110111111", + "1111111111101111111", + "11111111111011111111", + "111111111110111111111", + "1111111111101111111111", + "11111111111011111111111", + "111111111110111111111111", + "1111111111101111111111111", + "11111111111011111111111111", + "111111111110111111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111", + "111111111110111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111", + "1111111111101111111111111111111111", + "11111111111011111111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111", + "11111111111011111111111111111111111111", + "111111111110111111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111", + "111111111110111111111111111111111111111111", + "1111111111101111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11", + "1111", + "111111", + "11111111", + "1111111111", + "111111111110", + "11111111111011", + "1111111111101111", + "111111111110111111", + "11111111111011111111", + "1111111111101111111111", + "111111111110111111111111", + "11111111111011111111111111", + "1111111111101111111111111111", + "111111111110111111111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111", + "111111111110111111111111111111111111", + "11111111111011111111111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "111", + "111111", + "111111111", + "111111111110", + "111111111110111", + "111111111110111111", + "111111111110111111111", + "111111111110111111111111", + "111111111110111111111111111", + "111111111110111111111111111111", + "111111111110111111111111111111111", + "111111111110111111111111111111111111", + "111111111110111111111111111111111111111", + "111111111110111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111", + "11111111", + "111111111110", + "1111111111101111", + "11111111111011111111", + "111111111110111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111", + "1111111111101111", + "111111111110111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111", + "11111111111011111111", + "111111111110111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111", + "1111111111101111111111", + "111111111110111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1", + "11", + "111", + "1111", + "11111", + "111111", + "1111111", + "11111111", + "111111111", + "1111111111", + "11111111111", + "111111111110", + "1111111111101", + "11111111111011", + "111111111110111", + "1111111111101111", + "11111111111011111", + "111111111110111111", + "1111111111101111111", + "11111111111011111111", + "111111111110111111111", + "1111111111101111111111", + "11111111111011111111111", + "111111111110111111111111", + "1111111111101111111111111", + "11111111111011111111111111", + "111111111110111111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111", + "111111111110111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111", + "1111111111101111111111111111111111", + "11111111111011111111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111", + "11111111111011111111111111111111111111", + "111111111110111111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111", + "111111111110111111111111111111111111111111", + "1111111111101111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11", + "1111", + "111111", + "11111111", + "1111111111", + "111111111110", + "11111111111011", + "1111111111101111", + "111111111110111111", + "11111111111011111111", + "1111111111101111111111", + "111111111110111111111111", + "11111111111011111111111111", + "1111111111101111111111111111", + "111111111110111111111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111", + "111111111110111111111111111111111111", + "11111111111011111111111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "111", + "111111", + "111111111", + "111111111110", + "111111111110111", + "111111111110111111", + "111111111110111111111", + "111111111110111111111111", + "111111111110111111111111111", + "111111111110111111111111111111", + "111111111110111111111111111111111", + "111111111110111111111111111111111111", + "111111111110111111111111111111111111111", + "111111111110111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111", + "11111111", + "111111111110", + "1111111111101111", + "11111111111011111111", + "111111111110111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111", + "1111111111101111", + "111111111110111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111", + "11111111111011111111", + "111111111110111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111", + "1111111111101111111111", + "111111111110111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1", + "11", + "111", + "1111", + "11111", + "111111", + "1111111", + "11111111", + "111111111", + "1111111111", + "11111111111", + "111111111110", + "1111111111101", + "11111111111011", + "111111111110111", + "1111111111101111", + "11111111111011111", + "111111111110111111", + "1111111111101111111", + "11111111111011111111", + "111111111110111111111", + "1111111111101111111111", + "11111111111011111111111", + "111111111110111111111111", + "1111111111101111111111111", + "11111111111011111111111111", + "111111111110111111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111", + "111111111110111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111", + "1111111111101111111111111111111111", + "11111111111011111111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111", + "11111111111011111111111111111111111111", + "111111111110111111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111", + "111111111110111111111111111111111111111111", + "1111111111101111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11", + "1111", + "111111", + "11111111", + "1111111111", + "111111111110", + "11111111111011", + "1111111111101111", + "111111111110111111", + "11111111111011111111", + "1111111111101111111111", + "111111111110111111111111", + "11111111111011111111111111", + "1111111111101111111111111111", + "111111111110111111111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111", + "111111111110111111111111111111111111", + "11111111111011111111111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "111", + "111111", + "111111111", + "111111111110", + "111111111110111", + "111111111110111111", + "111111111110111111111", + "111111111110111111111111", + "111111111110111111111111111", + "111111111110111111111111111111", + "111111111110111111111111111111111", + "111111111110111111111111111111111111", + "111111111110111111111111111111111111111", + "111111111110111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111", + "11111111", + "111111111110", + "1111111111101111", + "11111111111011111111", + "111111111110111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111", + "1111111111101111", + "111111111110111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111", + "11111111111011111111", + "111111111110111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111", + "1111111111101111111111", + "111111111110111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1", + "11", + "111", + "1111", + "11111", + "111111", + "1111111", + "11111111", + "111111111", + "1111111111", + "11111111111", + "111111111110", + "1111111111101", + "11111111111011", + "111111111110111", + "1111111111101111", + "11111111111011111", + "111111111110111111", + "1111111111101111111", + "11111111111011111111", + "111111111110111111111", + "1111111111101111111111", + "11111111111011111111111", + "111111111110111111111111", + "1111111111101111111111111", + "11111111111011111111111111", + "111111111110111111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111", + "111111111110111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111", + "1111111111101111111111111111111111", + "11111111111011111111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111", + "11111111111011111111111111111111111111", + "111111111110111111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111", + "111111111110111111111111111111111111111111", + "1111111111101111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11", + "1111", + "111111", + "11111111", + "1111111111", + "111111111110", + "11111111111011", + "1111111111101111", + "111111111110111111", + "11111111111011111111", + "1111111111101111111111", + "111111111110111111111111", + "11111111111011111111111111", + "1111111111101111111111111111", + "111111111110111111111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111", + "111111111110111111111111111111111111", + "11111111111011111111111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "111", + "111111", + "111111111", + "111111111110", + "111111111110111", + "111111111110111111", + "111111111110111111111", + "111111111110111111111111", + "111111111110111111111111111", + "111111111110111111111111111111", + "111111111110111111111111111111111", + "111111111110111111111111111111111111", + "111111111110111111111111111111111111111", + "111111111110111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111", + "11111111", + "111111111110", + "1111111111101111", + "11111111111011111111", + "111111111110111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111", + "1111111111101111", + "111111111110111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111", + "11111111111011111111", + "111111111110111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111", + "1111111111101111111111", + "111111111110111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1", + "11", + "111", + "1111", + "11111", + "111111", + "1111111", + "11111111", + "111111111", + "1111111111", + "11111111111", + "111111111110", + "1111111111101", + "11111111111011", + "111111111110111", + "1111111111101111", + "11111111111011111", + "111111111110111111", + "1111111111101111111", + "11111111111011111111", + "111111111110111111111", + "1111111111101111111111", + "11111111111011111111111", + "111111111110111111111111", + "1111111111101111111111111", + "11111111111011111111111111", + "111111111110111111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111", + "111111111110111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111", + "1111111111101111111111111111111111", + "11111111111011111111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111", + "11111111111011111111111111111111111111", + "111111111110111111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111", + "111111111110111111111111111111111111111111", + "1111111111101111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11", + "1111", + "111111", + "11111111", + "1111111111", + "111111111110", + "11111111111011", + "1111111111101111", + "111111111110111111", + "11111111111011111111", + "1111111111101111111111", + "111111111110111111111111", + "11111111111011111111111111", + "1111111111101111111111111111", + "111111111110111111111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111", + "111111111110111111111111111111111111", + "11111111111011111111111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "111", + "111111", + "111111111", + "111111111110", + "111111111110111", + "111111111110111111", + "111111111110111111111", + "111111111110111111111111", + "111111111110111111111111111", + "111111111110111111111111111111", + "111111111110111111111111111111111", + "111111111110111111111111111111111111", + "111111111110111111111111111111111111111", + "111111111110111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111", + "11111111", + "111111111110", + "1111111111101111", + "11111111111011111111", + "111111111110111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111", + "1111111111101111", + "111111111110111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111", + "11111111111011111111", + "111111111110111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111", + "1111111111101111111111", + "111111111110111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1", + "11", + "111", + "1111", + "11111", + "111111", + "1111111", + "11111111", + "111111111", + "1111111111", + "11111111111", + "111111111110", + "1111111111101", + "11111111111011", + "111111111110111", + "1111111111101111", + "11111111111011111", + "111111111110111111", + "1111111111101111111", + "11111111111011111111", + "111111111110111111111", + "1111111111101111111111", + "11111111111011111111111", + "111111111110111111111111", + "1111111111101111111111111", + "11111111111011111111111111", + "111111111110111111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111", + "111111111110111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111", + "1111111111101111111111111111111111", + "11111111111011111111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111", + "11111111111011111111111111111111111111", + "111111111110111111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111", + "111111111110111111111111111111111111111111", + "1111111111101111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11", + "1111", + "111111", + "11111111", + "1111111111", + "111111111110", + "11111111111011", + "1111111111101111", + "111111111110111111", + "11111111111011111111", + "1111111111101111111111", + "111111111110111111111111", + "11111111111011111111111111", + "1111111111101111111111111111", + "111111111110111111111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111", + "111111111110111111111111111111111111", + "11111111111011111111111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "111", + "111111", + "111111111", + "111111111110", + "111111111110111", + "111111111110111111", + "111111111110111111111", + "111111111110111111111111", + "111111111110111111111111111", + "111111111110111111111111111111", + "111111111110111111111111111111111", + "111111111110111111111111111111111111", + "111111111110111111111111111111111111111", + "111111111110111111111111111111111111111111", + "111111111110111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111", + "11111111", + "111111111110", + "1111111111101111", + "11111111111011111111", + "111111111110111111111111", + "1111111111101111111111111111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111", + "1111111111101111", + "111111111110111111111111", + "11111111111011111111111111111111", + "1111111111101111111111111111111111111111", + "111111111110111111111111111111111111111111111111", + "11111111111011111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111", + "11111111111011111111", + "111111111110111111111111111111", + "1111111111101111111111111111111111111111", + "11111111111011111111111111111111111111111111111111", + "111111111110111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111", + "1111111111101111111111", + "111111111110111111111111111111111", + "11111111111011111111111111111111111111111111", + "1111111111101111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111", + "11111111111011111111111111111111", + "111111111110111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "1111111111101111111111111111111", + "11111111111011111111111111111111111111111111111111111111111111", + }, +}, +{ + .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1111111111101111111111111111111111111111111111111111111111111111", + "11111111111011111111111111111111", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000001", + "1000000000010", + "10000000000100", + "100000000001000", + "1000000000010000", + "10000000000100000", + "100000000001000000", + "1000000000010000000", + "10000000000100000000", + "100000000001000000000", + "1000000000010000000000", + "10000000000100000000000", + "100000000001000000000000", + "1000000000010000000000000", + "10000000000100000000000000", + "100000000001000000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000", + "100000000001000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000", + "1000000000010000000000000000000000", + "10000000000100000000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000", + "10000000000100000000000000000000000000", + "100000000001000000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000", + "100000000001000000000000000000000000000000", + "1000000000010000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000001", + "10000000000100", + "1000000000010000", + "100000000001000000", + "10000000000100000000", + "1000000000010000000000", + "100000000001000000000000", + "10000000000100000000000000", + "1000000000010000000000000000", + "100000000001000000000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000", + "100000000001000000000000000000000000", + "10000000000100000000000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000001", + "100000000001000", + "100000000001000000", + "100000000001000000000", + "100000000001000000000000", + "100000000001000000000000000", + "100000000001000000000000000000", + "100000000001000000000000000000000", + "100000000001000000000000000000000000", + "100000000001000000000000000000000000000", + "100000000001000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000001", + "1000000000010000", + "10000000000100000000", + "100000000001000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000010000", + "100000000001000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000100000000", + "100000000001000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000010000000000", + "100000000001000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000001", + "1000000000010", + "10000000000100", + "100000000001000", + "1000000000010000", + "10000000000100000", + "100000000001000000", + "1000000000010000000", + "10000000000100000000", + "100000000001000000000", + "1000000000010000000000", + "10000000000100000000000", + "100000000001000000000000", + "1000000000010000000000000", + "10000000000100000000000000", + "100000000001000000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000", + "100000000001000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000", + "1000000000010000000000000000000000", + "10000000000100000000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000", + "10000000000100000000000000000000000000", + "100000000001000000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000", + "100000000001000000000000000000000000000000", + "1000000000010000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000001", + "10000000000100", + "1000000000010000", + "100000000001000000", + "10000000000100000000", + "1000000000010000000000", + "100000000001000000000000", + "10000000000100000000000000", + "1000000000010000000000000000", + "100000000001000000000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000", + "100000000001000000000000000000000000", + "10000000000100000000000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000001", + "100000000001000", + "100000000001000000", + "100000000001000000000", + "100000000001000000000000", + "100000000001000000000000000", + "100000000001000000000000000000", + "100000000001000000000000000000000", + "100000000001000000000000000000000000", + "100000000001000000000000000000000000000", + "100000000001000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000001", + "1000000000010000", + "10000000000100000000", + "100000000001000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000010000", + "100000000001000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000100000000", + "100000000001000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000010000000000", + "100000000001000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000001", + "1000000000010", + "10000000000100", + "100000000001000", + "1000000000010000", + "10000000000100000", + "100000000001000000", + "1000000000010000000", + "10000000000100000000", + "100000000001000000000", + "1000000000010000000000", + "10000000000100000000000", + "100000000001000000000000", + "1000000000010000000000000", + "10000000000100000000000000", + "100000000001000000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000", + "100000000001000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000", + "1000000000010000000000000000000000", + "10000000000100000000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000", + "10000000000100000000000000000000000000", + "100000000001000000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000", + "100000000001000000000000000000000000000000", + "1000000000010000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000001", + "10000000000100", + "1000000000010000", + "100000000001000000", + "10000000000100000000", + "1000000000010000000000", + "100000000001000000000000", + "10000000000100000000000000", + "1000000000010000000000000000", + "100000000001000000000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000", + "100000000001000000000000000000000000", + "10000000000100000000000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000001", + "100000000001000", + "100000000001000000", + "100000000001000000000", + "100000000001000000000000", + "100000000001000000000000000", + "100000000001000000000000000000", + "100000000001000000000000000000000", + "100000000001000000000000000000000000", + "100000000001000000000000000000000000000", + "100000000001000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000001", + "1000000000010000", + "10000000000100000000", + "100000000001000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000010000", + "100000000001000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000100000000", + "100000000001000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000010000000000", + "100000000001000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 12.33999999999999986 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000001", + "1000000000010", + "10000000000100", + "100000000001000", + "1000000000010000", + "10000000000100000", + "100000000001000000", + "1000000000010000000", + "10000000000100000000", + "100000000001000000000", + "1000000000010000000000", + "10000000000100000000000", + "100000000001000000000000", + "1000000000010000000000000", + "10000000000100000000000000", + "100000000001000000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000", + "100000000001000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000", + "1000000000010000000000000000000000", + "10000000000100000000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000", + "10000000000100000000000000000000000000", + "100000000001000000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000", + "100000000001000000000000000000000000000000", + "1000000000010000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000001", + "10000000000100", + "1000000000010000", + "100000000001000000", + "10000000000100000000", + "1000000000010000000000", + "100000000001000000000000", + "10000000000100000000000000", + "1000000000010000000000000000", + "100000000001000000000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000", + "100000000001000000000000000000000000", + "10000000000100000000000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000001", + "100000000001000", + "100000000001000000", + "100000000001000000000", + "100000000001000000000000", + "100000000001000000000000000", + "100000000001000000000000000000", + "100000000001000000000000000000000", + "100000000001000000000000000000000000", + "100000000001000000000000000000000000000", + "100000000001000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000001", + "1000000000010000", + "10000000000100000000", + "100000000001000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000010000", + "100000000001000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000100000000", + "100000000001000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000010000000000", + "100000000001000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = 0.00000000000000000 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000001", + "1000000000010", + "10000000000100", + "100000000001000", + "1000000000010000", + "10000000000100000", + "100000000001000000", + "1000000000010000000", + "10000000000100000000", + "100000000001000000000", + "1000000000010000000000", + "10000000000100000000000", + "100000000001000000000000", + "1000000000010000000000000", + "10000000000100000000000000", + "100000000001000000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000", + "100000000001000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000", + "1000000000010000000000000000000000", + "10000000000100000000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000", + "10000000000100000000000000000000000000", + "100000000001000000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000", + "100000000001000000000000000000000000000000", + "1000000000010000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000001", + "10000000000100", + "1000000000010000", + "100000000001000000", + "10000000000100000000", + "1000000000010000000000", + "100000000001000000000000", + "10000000000100000000000000", + "1000000000010000000000000000", + "100000000001000000000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000", + "100000000001000000000000000000000000", + "10000000000100000000000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000001", + "100000000001000", + "100000000001000000", + "100000000001000000000", + "100000000001000000000000", + "100000000001000000000000000", + "100000000001000000000000000000", + "100000000001000000000000000000000", + "100000000001000000000000000000000000", + "100000000001000000000000000000000000000", + "100000000001000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000001", + "1000000000010000", + "10000000000100000000", + "100000000001000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000010000", + "100000000001000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000100000000", + "100000000001000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000010000000000", + "100000000001000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = -54.32099999999999795 }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000001", + "1000000000010", + "10000000000100", + "100000000001000", + "1000000000010000", + "10000000000100000", + "100000000001000000", + "1000000000010000000", + "10000000000100000000", + "100000000001000000000", + "1000000000010000000000", + "10000000000100000000000", + "100000000001000000000000", + "1000000000010000000000000", + "10000000000100000000000000", + "100000000001000000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000", + "100000000001000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000", + "1000000000010000000000000000000000", + "10000000000100000000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000", + "10000000000100000000000000000000000000", + "100000000001000000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000", + "100000000001000000000000000000000000000000", + "1000000000010000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000001", + "10000000000100", + "1000000000010000", + "100000000001000000", + "10000000000100000000", + "1000000000010000000000", + "100000000001000000000000", + "10000000000100000000000000", + "1000000000010000000000000000", + "100000000001000000000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000", + "100000000001000000000000000000000000", + "10000000000100000000000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000001", + "100000000001000", + "100000000001000000", + "100000000001000000000", + "100000000001000000000000", + "100000000001000000000000000", + "100000000001000000000000000000", + "100000000001000000000000000000000", + "100000000001000000000000000000000000", + "100000000001000000000000000000000000000", + "100000000001000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000001", + "1000000000010000", + "10000000000100000000", + "100000000001000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000010000", + "100000000001000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000100000000", + "100000000001000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000010000000000", + "100000000001000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = true, .value = DBL_MIN }, + .max = { .set = true, .value = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000000000000 }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000001", + "1000000000010", + "10000000000100", + "100000000001000", + "1000000000010000", + "10000000000100000", + "100000000001000000", + "1000000000010000000", + "10000000000100000000", + "100000000001000000000", + "1000000000010000000000", + "10000000000100000000000", + "100000000001000000000000", + "1000000000010000000000000", + "10000000000100000000000000", + "100000000001000000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000", + "100000000001000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000", + "1000000000010000000000000000000000", + "10000000000100000000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000", + "10000000000100000000000000000000000000", + "100000000001000000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000", + "100000000001000000000000000000000000000000", + "1000000000010000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000001", + "10000000000100", + "1000000000010000", + "100000000001000000", + "10000000000100000000", + "1000000000010000000000", + "100000000001000000000000", + "10000000000100000000000000", + "1000000000010000000000000000", + "100000000001000000000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000", + "100000000001000000000000000000000000", + "10000000000100000000000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000001", + "100000000001000", + "100000000001000000", + "100000000001000000000", + "100000000001000000000000", + "100000000001000000000000000", + "100000000001000000000000000000", + "100000000001000000000000000000000", + "100000000001000000000000000000000000", + "100000000001000000000000000000000000000", + "100000000001000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000001", + "1000000000010000", + "10000000000100000000", + "100000000001000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000010000", + "100000000001000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000100000000", + "100000000001000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000010000000000", + "100000000001000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000001", + "1000000000010", + "10000000000100", + "100000000001000", + "1000000000010000", + "10000000000100000", + "100000000001000000", + "1000000000010000000", + "10000000000100000000", + "100000000001000000000", + "1000000000010000000000", + "10000000000100000000000", + "100000000001000000000000", + "1000000000010000000000000", + "10000000000100000000000000", + "100000000001000000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000", + "100000000001000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000", + "1000000000010000000000000000000000", + "10000000000100000000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000", + "10000000000100000000000000000000000000", + "100000000001000000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000", + "100000000001000000000000000000000000000000", + "1000000000010000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000001", + "10000000000100", + "1000000000010000", + "100000000001000000", + "10000000000100000000", + "1000000000010000000000", + "100000000001000000000000", + "10000000000100000000000000", + "1000000000010000000000000000", + "100000000001000000000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000", + "100000000001000000000000000000000000", + "10000000000100000000000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000001", + "100000000001000", + "100000000001000000", + "100000000001000000000", + "100000000001000000000000", + "100000000001000000000000000", + "100000000001000000000000000000", + "100000000001000000000000000000000", + "100000000001000000000000000000000000", + "100000000001000000000000000000000000000", + "100000000001000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000001", + "1000000000010000", + "10000000000100000000", + "100000000001000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000010000", + "100000000001000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000100000000", + "100000000001000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000010000000000", + "100000000001000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1", + "10", + "100", + "1000", + "10000", + "100000", + "1000000", + "10000000", + "100000000", + "1000000000", + "10000000000", + "100000000001", + "1000000000010", + "10000000000100", + "100000000001000", + "1000000000010000", + "10000000000100000", + "100000000001000000", + "1000000000010000000", + "10000000000100000000", + "100000000001000000000", + "1000000000010000000000", + "10000000000100000000000", + "100000000001000000000000", + "1000000000010000000000000", + "10000000000100000000000000", + "100000000001000000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000", + "100000000001000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000", + "1000000000010000000000000000000000", + "10000000000100000000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000", + "10000000000100000000000000000000000000", + "100000000001000000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000", + "100000000001000000000000000000000000000000", + "1000000000010000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10", + "1000", + "100000", + "10000000", + "1000000000", + "100000000001", + "10000000000100", + "1000000000010000", + "100000000001000000", + "10000000000100000000", + "1000000000010000000000", + "100000000001000000000000", + "10000000000100000000000000", + "1000000000010000000000000000", + "100000000001000000000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000", + "100000000001000000000000000000000000", + "10000000000100000000000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "100", + "100000", + "100000000", + "100000000001", + "100000000001000", + "100000000001000000", + "100000000001000000000", + "100000000001000000000000", + "100000000001000000000000000", + "100000000001000000000000000000", + "100000000001000000000000000000000", + "100000000001000000000000000000000000", + "100000000001000000000000000000000000000", + "100000000001000000000000000000000000000000", + "100000000001000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000", + "10000000", + "100000000001", + "1000000000010000", + "10000000000100000000", + "100000000001000000000000", + "1000000000010000000000000000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000", + "1000000000010000", + "100000000001000000000000", + "10000000000100000000000000000000", + "1000000000010000000000000000000000000000", + "100000000001000000000000000000000000000000000000", + "10000000000100000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000", + "10000000000100000000", + "100000000001000000000000000000", + "1000000000010000000000000000000000000000", + "10000000000100000000000000000000000000000000000000", + "100000000001000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000", + "1000000000010000000000", + "100000000001000000000000000000000", + "10000000000100000000000000000000000000000000", + "1000000000010000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000", + "10000000000100000000000000000000", + "100000000001000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "1000000000010000000000000000000", + "10000000000100000000000000000000000000000000000000000000000000", + }, +}, +{ + .value = DBL_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { + "root", + "1000000000010000000000000000000000000000000000000000000000000000", + "10000000000100000000000000000000", + }, }, diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_int32.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_int32.cstruct index 9132577..5e8880e 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_int32.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_int32.cstruct @@ -1,96 +1,221 @@ -// This is a copy of test vectors from the mongodb/mongo repository. -// The order of edges is rearranged to permit exact matching. -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=1, { +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` +// clang-format off +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "0111", "0", "01", "011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "0111", "01", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "0111", "011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(13), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "1000", "1", "10", "100", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "1000", "10", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "1000", "100", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000000111", "1", @@ -124,8 +249,14 @@ "10000000000000000000000000000", "100000000000000000000000000001", "1000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000000111", "10", @@ -143,8 +274,14 @@ "10000000000000000000000000", "1000000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000000111", "100", @@ -157,8 +294,14 @@ "100000000000000000000000", "100000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000000111", "1000", @@ -168,42 +311,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000", "10000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000000", "1000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "000111", "0", @@ -211,48 +396,108 @@ "000", "0001", "00011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "000111", "00", "0001", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "000111", "000", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "000111", "0001", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "001000", "0", @@ -260,48 +505,108 @@ "001", "0010", "00100", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "001000", "00", "0010", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "001000", "001", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "001000", "0010", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000000111", "1", @@ -335,8 +640,14 @@ "10000000000000000000000000000", "100000000000000000000000000001", "1000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000000111", "10", @@ -354,8 +665,14 @@ "10000000000000000000000000", "1000000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000000111", "100", @@ -368,8 +685,14 @@ "100000000000000000000000", "100000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000000111", "1000", @@ -379,42 +702,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000", "10000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000000", "1000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000000111", "0", @@ -427,8 +792,14 @@ "00000000", "000000001", "0000000011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000000111", "00", @@ -436,47 +807,101 @@ "000000", "00000000", "0000000011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000000111", "000", "000000", "000000001", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000000111", "0000", "00000000", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000000111", "00000000", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000000111", "0000000011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000000111", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000001000", "0", @@ -489,8 +914,14 @@ "00000001", "000000010", "0000000100", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000001000", "00", @@ -498,47 +929,101 @@ "000000", "00000001", "0000000100", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000001000", "000", "000000", "000000010", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000001000", "0000", "00000001", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000001000", "00000001", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000001000", "0000000100", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000001000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000001000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000001000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000001000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000000111", "1", @@ -572,8 +1057,14 @@ "10000000000000000000000000000", "100000000000000000000000000001", "1000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000000111", "10", @@ -591,8 +1082,14 @@ "10000000000000000000000000", "1000000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000000111", "100", @@ -605,8 +1102,14 @@ "100000000000000000000000", "100000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000000111", "1000", @@ -616,42 +1119,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000", "10000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000000", "1000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "0000000000000000000000000000111", "0", @@ -684,8 +1229,14 @@ "0000000000000000000000000000", "00000000000000000000000000001", "000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "0000000000000000000000000000111", "00", @@ -703,8 +1254,14 @@ "00000000000000000000000000", "0000000000000000000000000000", "000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "0000000000000000000000000000111", "000", @@ -717,8 +1274,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "0000000000000000000000000000111", "0000", @@ -728,41 +1291,83 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "0000000000000000000000000000111", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "0000000000000000000000000000111", "0000000000", "00000000000000000000", "000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "0000000000000000000000000000111", "00000000000", "0000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "0000000000000000000000000000111", "0000000000000000", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "0000000000000000000000000000111", -}}, -{.value=7, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "0000000000000000000000000000111", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000001000", "0", @@ -796,8 +1401,14 @@ "00000000000000000000000000001", "000000000000000000000000000010", "0000000000000000000000000000100", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000001000", "00", @@ -815,8 +1426,14 @@ "00000000000000000000000000", "0000000000000000000000000000", "000000000000000000000000000010", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000001000", "000", @@ -829,8 +1446,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000010", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000001000", "0000", @@ -840,42 +1463,84 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000001000", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000001000", "0000000000", "00000000000000000000", "000000000000000000000000000010", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000001000", "00000000000", "0000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000001000", "0000000000000000", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000001000", "0000000000000000000000000000100", -}}, -{.value=7, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000001000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000000111", "1", @@ -909,8 +1574,14 @@ "10000000000000000000000000000", "100000000000000000000000000001", "1000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000000111", "10", @@ -928,8 +1599,14 @@ "10000000000000000000000000", "1000000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000000111", "100", @@ -942,8 +1619,14 @@ "100000000000000000000000", "100000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000000111", "1000", @@ -953,42 +1636,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000", "10000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000000", "1000000000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000000111", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000000111", "1", @@ -1022,8 +1747,14 @@ "10000000000000000000000000000", "100000000000000000000000000001", "1000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000000111", "10", @@ -1041,8 +1772,14 @@ "10000000000000000000000000", "1000000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000000111", "100", @@ -1055,8 +1792,14 @@ "100000000000000000000000", "100000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000000111", "1000", @@ -1066,42 +1809,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000", "10000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000000", "1000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000000111", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000000111", "1", @@ -1135,8 +1920,14 @@ "10000000000000000000000000000", "100000000000000000000000000001", "1000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000000111", "10", @@ -1154,8 +1945,14 @@ "10000000000000000000000000", "1000000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000000111", "100", @@ -1168,8 +1965,14 @@ "100000000000000000000000", "100000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000000111", "1000", @@ -1179,42 +1982,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000", "10000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000000", "1000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000000111", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000000111", "1", @@ -1248,8 +2093,14 @@ "10000000000000000000000000000", "100000000000000000000000000001", "1000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000000111", "10", @@ -1267,8 +2118,14 @@ "10000000000000000000000000", "1000000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000000111", "100", @@ -1281,8 +2138,14 @@ "100000000000000000000000", "100000000000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000000111", "1000", @@ -1292,42 +2155,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000", "10000000000000000000", "100000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000000111", "10000000000", "1000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000000111", "1000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000000111", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "100000", "1", @@ -1335,48 +2240,108 @@ "100", "1000", "10000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "100000", "10", "1000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "100000", "100", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "100000", "1000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(32), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "100001", "1", @@ -1384,48 +2349,108 @@ "100", "1000", "10000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "100001", "10", "1000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "100001", "100", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "100001", "1000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000100000", "1", @@ -1459,8 +2484,14 @@ "10000000000000000000000000100", "100000000000000000000000001000", "1000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000100000", "10", @@ -1478,8 +2509,14 @@ "10000000000000000000000000", "1000000000000000000000000010", "100000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000100000", "100", @@ -1492,8 +2529,14 @@ "100000000000000000000000", "100000000000000000000000001", "100000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000100000", "1000", @@ -1503,42 +2546,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000010", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000", "10000000000000000000", "100000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000000", "1000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000100000", "0", @@ -1551,8 +2636,14 @@ "00000100", "000001000", "0000010000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000100000", "00", @@ -1560,47 +2651,101 @@ "000001", "00000100", "0000010000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000100000", "000", "000001", "000001000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000100000", "0000", "00000100", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000100000", "00000100", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000100000", "0000010000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000100000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000100001", "0", @@ -1613,8 +2758,14 @@ "00000100", "000001000", "0000010000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000100001", "00", @@ -1622,47 +2773,101 @@ "000001", "00000100", "0000010000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000100001", "000", "000001", "000001000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000100001", "0000", "00000100", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000100001", "00000100", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000100001", "0000010000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000100001", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000100001", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000100001", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000100001", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000100000", "1", @@ -1696,8 +2901,14 @@ "10000000000000000000000000100", "100000000000000000000000001000", "1000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000100000", "10", @@ -1715,8 +2926,14 @@ "10000000000000000000000000", "1000000000000000000000000010", "100000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000100000", "100", @@ -1729,8 +2946,14 @@ "100000000000000000000000", "100000000000000000000000001", "100000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000100000", "1000", @@ -1740,42 +2963,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000010", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000", "10000000000000000000", "100000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000000", "1000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "0000000000000000000000000100000", "0", @@ -1808,8 +3073,14 @@ "0000000000000000000000000100", "00000000000000000000000001000", "000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "0000000000000000000000000100000", "00", @@ -1827,8 +3098,14 @@ "00000000000000000000000001", "0000000000000000000000000100", "000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "0000000000000000000000000100000", "000", @@ -1841,8 +3118,14 @@ "000000000000000000000000", "000000000000000000000000010", "000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "0000000000000000000000000100000", "0000", @@ -1852,41 +3135,83 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000100", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "0000000000000000000000000100000", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "0000000000000000000000000100000", "0000000000", "00000000000000000000", "000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "0000000000000000000000000100000", "00000000000", "0000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "0000000000000000000000000100000", "0000000000000000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "0000000000000000000000000100000", -}}, -{.value=32, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "0000000000000000000000000100000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000100001", "0", @@ -1920,8 +3245,14 @@ "00000000000000000000000000100", "000000000000000000000000001000", "0000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000100001", "00", @@ -1939,8 +3270,14 @@ "00000000000000000000000000", "0000000000000000000000000010", "000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000100001", "000", @@ -1953,8 +3290,14 @@ "000000000000000000000000", "000000000000000000000000001", "000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000100001", "0000", @@ -1964,42 +3307,84 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000010", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000100001", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000100001", "0000000000", "00000000000000000000", "000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000100001", "00000000000", "0000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000100001", "0000000000000000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000100001", "0000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000100001", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000100000", "1", @@ -2033,8 +3418,14 @@ "10000000000000000000000000100", "100000000000000000000000001000", "1000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000100000", "10", @@ -2052,8 +3443,14 @@ "10000000000000000000000000", "1000000000000000000000000010", "100000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000100000", "100", @@ -2066,8 +3463,14 @@ "100000000000000000000000", "100000000000000000000000001", "100000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000100000", "1000", @@ -2077,42 +3480,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000010", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000", "10000000000000000000", "100000000000000000000000001000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000000", "1000000000000000000000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000100000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000100000", "1", @@ -2146,8 +3591,14 @@ "10000000000000000000000000100", "100000000000000000000000001000", "1000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000100000", "10", @@ -2165,8 +3616,14 @@ "10000000000000000000000000", "1000000000000000000000000010", "100000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000100000", "100", @@ -2179,8 +3636,14 @@ "100000000000000000000000", "100000000000000000000000001", "100000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000100000", "1000", @@ -2190,42 +3653,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000010", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000", "10000000000000000000", "100000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000000", "1000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000100000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000100000", "1", @@ -2259,8 +3764,14 @@ "10000000000000000000000000100", "100000000000000000000000001000", "1000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000100000", "10", @@ -2278,8 +3789,14 @@ "10000000000000000000000000", "1000000000000000000000000010", "100000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000100000", "100", @@ -2292,8 +3809,14 @@ "100000000000000000000000", "100000000000000000000000001", "100000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000100000", "1000", @@ -2303,42 +3826,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000010", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000", "10000000000000000000", "100000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000000", "1000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000100000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000100000", "1", @@ -2372,8 +3937,14 @@ "10000000000000000000000000100", "100000000000000000000000001000", "1000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000100000", "10", @@ -2391,8 +3962,14 @@ "10000000000000000000000000", "1000000000000000000000000010", "100000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000100000", "100", @@ -2405,8 +3982,14 @@ "100000000000000000000000", "100000000000000000000000001", "100000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000100000", "1000", @@ -2416,42 +3999,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000010", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000", "10000000000000000000", "100000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000100000", "10000000000", "1000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000100000", "1000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000100000", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "01111111111", "0", @@ -2464,8 +4089,14 @@ "01111111", "011111111", "0111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "01111111111", "01", @@ -2473,47 +4104,101 @@ "011111", "01111111", "0111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "01111111111", "011", "011111", "011111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "01111111111", "0111", "01111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "01111111111", "01111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "01111111111", "0111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "01111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "01111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "01111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "01111111111", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000", "1", @@ -2526,8 +4211,14 @@ "10000000", "100000000", "1000000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000", "10", @@ -2535,47 +4226,101 @@ "100000", "10000000", "1000000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000", "100", "100000", "100000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000", "1000", "10000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000", "10000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000", "1000000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000001111111111", "1", @@ -2609,8 +4354,14 @@ "10000000000000000000001111111", "100000000000000000000011111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000001111111111", "10", @@ -2628,8 +4379,14 @@ "10000000000000000000001111", "1000000000000000000000111111", "100000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000001111111111", "100", @@ -2642,8 +4399,14 @@ "100000000000000000000011", "100000000000000000000011111", "100000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000001111111111", "1000", @@ -2653,42 +4416,84 @@ "10000000000000000000", "100000000000000000000011", "1000000000000000000000111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000", "1000000000000000", "100000000000000000000011", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000", "10000000000000000000", "100000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000000", "1000000000000000000000", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000001111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "0000000000000000000001111111111", "0", @@ -2721,8 +4526,14 @@ "0000000000000000000001111111", "00000000000000000000011111111", "000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "0000000000000000000001111111111", "00", @@ -2740,8 +4551,14 @@ "00000000000000000000011111", "0000000000000000000001111111", "000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "0000000000000000000001111111111", "000", @@ -2754,8 +4571,14 @@ "000000000000000000000111", "000000000000000000000111111", "000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "0000000000000000000001111111111", "0000", @@ -2765,41 +4588,83 @@ "00000000000000000000", "000000000000000000000111", "0000000000000000000001111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "0000000000000000000001111111111", "00000000", "0000000000000000", "000000000000000000000111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "0000000000000000000001111111111", "0000000000", "00000000000000000000", "000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "0000000000000000000001111111111", "00000000000", "0000000000000000000001", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "0000000000000000000001111111111", "0000000000000000", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "0000000000000000000001111111111", -}}, -{.value=1023, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "0000000000000000000001111111111", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000010000000000", "0", @@ -2833,8 +4698,14 @@ "00000000000000000000010000000", "000000000000000000000100000000", "0000000000000000000001000000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000010000000000", "00", @@ -2852,8 +4723,14 @@ "00000000000000000000010000", "0000000000000000000001000000", "000000000000000000000100000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000010000000000", "000", @@ -2866,8 +4743,14 @@ "000000000000000000000100", "000000000000000000000100000", "000000000000000000000100000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000010000000000", "0000", @@ -2877,42 +4760,84 @@ "00000000000000000000", "000000000000000000000100", "0000000000000000000001000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000010000000000", "00000000", "0000000000000000", "000000000000000000000100", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000010000000000", "0000000000", "00000000000000000000", "000000000000000000000100000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000010000000000", "00000000000", "0000000000000000000001", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000010000000000", "0000000000000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000010000000000", "0000000000000000000001000000000", -}}, -{.value=1023, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000010000000000", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000001111111111", "1", @@ -2946,8 +4871,14 @@ "10000000000000000000001111111", "100000000000000000000011111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000001111111111", "10", @@ -2965,8 +4896,14 @@ "10000000000000000000001111", "1000000000000000000000111111", "100000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000001111111111", "100", @@ -2979,8 +4916,14 @@ "100000000000000000000011", "100000000000000000000011111", "100000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000001111111111", "1000", @@ -2990,42 +4933,84 @@ "10000000000000000000", "100000000000000000000011", "1000000000000000000000111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000", "1000000000000000", "100000000000000000000011", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000", "10000000000000000000", "100000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000000", "1000000000000000000000", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000001111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000001111111111", "1", @@ -3059,8 +5044,14 @@ "10000000000000000000001111111", "100000000000000000000011111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000001111111111", "10", @@ -3078,8 +5069,14 @@ "10000000000000000000001111", "1000000000000000000000111111", "100000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000001111111111", "100", @@ -3092,8 +5089,14 @@ "100000000000000000000011", "100000000000000000000011111", "100000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000001111111111", "1000", @@ -3103,42 +5106,84 @@ "10000000000000000000", "100000000000000000000011", "1000000000000000000000111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000", "1000000000000000", "100000000000000000000011", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000", "10000000000000000000", "100000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000000", "1000000000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000001111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000001111111111", "1", @@ -3172,8 +5217,14 @@ "10000000000000000000001111111", "100000000000000000000011111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000001111111111", "10", @@ -3191,8 +5242,14 @@ "10000000000000000000001111", "1000000000000000000000111111", "100000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000001111111111", "100", @@ -3205,8 +5262,14 @@ "100000000000000000000011", "100000000000000000000011111", "100000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000001111111111", "1000", @@ -3216,42 +5279,84 @@ "10000000000000000000", "100000000000000000000011", "1000000000000000000000111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000", "1000000000000000", "100000000000000000000011", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000", "10000000000000000000", "100000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000000", "1000000000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000001111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000001111111111", "1", @@ -3285,8 +5390,14 @@ "10000000000000000000001111111", "100000000000000000000011111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000001111111111", "10", @@ -3304,8 +5415,14 @@ "10000000000000000000001111", "1000000000000000000000111111", "100000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000001111111111", "100", @@ -3318,8 +5435,14 @@ "100000000000000000000011", "100000000000000000000011111", "100000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000001111111111", "1000", @@ -3329,42 +5452,84 @@ "10000000000000000000", "100000000000000000000011", "1000000000000000000000111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000", "1000000000000000", "100000000000000000000011", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000", "10000000000000000000", "100000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000001111111111", "10000000000", "1000000000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000001111111111", "1000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000001111111111", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "0110110111100100101001100111011", "0", @@ -3397,8 +5562,14 @@ "0110110111100100101001100111", "01101101111001001010011001110", "011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "0110110111100100101001100111011", "01", @@ -3416,8 +5587,14 @@ "01101101111001001010011001", "0110110111100100101001100111", "011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "0110110111100100101001100111011", "011", @@ -3430,8 +5607,14 @@ "011011011110010010100110", "011011011110010010100110011", "011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "0110110111100100101001100111011", "0110", @@ -3441,41 +5624,83 @@ "01101101111001001010", "011011011110010010100110", "0110110111100100101001100111", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "0110110111100100101001100111011", "01101101", "0110110111100100", "011011011110010010100110", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "0110110111100100101001100111011", "0110110111", "01101101111001001010", "011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "0110110111100100101001100111011", "01101101111", "0110110111100100101001", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "0110110111100100101001100111011", "0110110111100100", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "0110110111100100101001100111011", -}}, -{.value=921850683, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "0110110111100100101001100111011", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "00110110111100100101001100111100", "0", @@ -3509,8 +5734,14 @@ "00110110111100100101001100111", "001101101111001001010011001111", "0011011011110010010100110011110", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "00110110111100100101001100111100", "00", @@ -3528,8 +5759,14 @@ "00110110111100100101001100", "0011011011110010010100110011", "001101101111001001010011001111", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "00110110111100100101001100111100", "001", @@ -3542,8 +5779,14 @@ "001101101111001001010011", "001101101111001001010011001", "001101101111001001010011001111", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "00110110111100100101001100111100", "0011", @@ -3553,42 +5796,84 @@ "00110110111100100101", "001101101111001001010011", "0011011011110010010100110011", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "00110110111100100101001100111100", "00110110", "0011011011110010", "001101101111001001010011", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "00110110111100100101001100111100", "0011011011", "00110110111100100101", "001101101111001001010011001111", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "00110110111100100101001100111100", "00110110111", "0011011011110010010100", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "00110110111100100101001100111100", "0011011011110010", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "00110110111100100101001100111100", "0011011011110010010100110011110", -}}, -{.value=921850683, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "00110110111100100101001100111100", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "10110110111100100101001100111011", "1", @@ -3622,8 +5907,14 @@ "10110110111100100101001100111", "101101101111001001010011001110", "1011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "10110110111100100101001100111011", "10", @@ -3641,8 +5932,14 @@ "10110110111100100101001100", "1011011011110010010100110011", "101101101111001001010011001110", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "10110110111100100101001100111011", "101", @@ -3655,8 +5952,14 @@ "101101101111001001010011", "101101101111001001010011001", "101101101111001001010011001110", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "10110110111100100101001100111011", "1011", @@ -3666,42 +5969,84 @@ "10110110111100100101", "101101101111001001010011", "1011011011110010010100110011", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "10110110111100100101001100111011", "10110110", "1011011011110010", "101101101111001001010011", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011", "10110110111100100101", "101101101111001001010011001110", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "10110110111100100101001100111011", "10110110111", "1011011011110010010100", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011110010", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "10110110111100100101001100111011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10110110111100100101001100111011", "1", @@ -3735,8 +6080,14 @@ "10110110111100100101001100111", "101101101111001001010011001110", "1011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10110110111100100101001100111011", "10", @@ -3754,8 +6105,14 @@ "10110110111100100101001100", "1011011011110010010100110011", "101101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10110110111100100101001100111011", "101", @@ -3768,8 +6125,14 @@ "101101101111001001010011", "101101101111001001010011001", "101101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10110110111100100101001100111011", "1011", @@ -3779,42 +6142,84 @@ "10110110111100100101", "101101101111001001010011", "1011011011110010010100110011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10110110111100100101001100111011", "10110110", "1011011011110010", "101101101111001001010011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011", "10110110111100100101", "101101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10110110111100100101001100111011", "10110110111", "1011011011110010010100", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011110010", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10110110111100100101001100111011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10110110111100100101001100111011", "1", @@ -3848,8 +6253,14 @@ "10110110111100100101001100111", "101101101111001001010011001110", "1011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10110110111100100101001100111011", "10", @@ -3867,8 +6278,14 @@ "10110110111100100101001100", "1011011011110010010100110011", "101101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10110110111100100101001100111011", "101", @@ -3881,8 +6298,14 @@ "101101101111001001010011", "101101101111001001010011001", "101101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10110110111100100101001100111011", "1011", @@ -3892,42 +6315,84 @@ "10110110111100100101", "101101101111001001010011", "1011011011110010010100110011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10110110111100100101001100111011", "10110110", "1011011011110010", "101101101111001001010011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011", "10110110111100100101", "101101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10110110111100100101001100111011", "10110110111", "1011011011110010010100", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011110010", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10110110111100100101001100111011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10110110111100100101001100111011", "1", @@ -3961,8 +6426,14 @@ "10110110111100100101001100111", "101101101111001001010011001110", "1011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10110110111100100101001100111011", "10", @@ -3980,8 +6451,14 @@ "10110110111100100101001100", "1011011011110010010100110011", "101101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10110110111100100101001100111011", "101", @@ -3994,8 +6471,14 @@ "101101101111001001010011", "101101101111001001010011001", "101101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10110110111100100101001100111011", "1011", @@ -4005,42 +6488,84 @@ "10110110111100100101", "101101101111001001010011", "1011011011110010010100110011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10110110111100100101001100111011", "10110110", "1011011011110010", "101101101111001001010011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011", "10110110111100100101", "101101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10110110111100100101001100111011", "10110110111", "1011011011110010010100", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011110010", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10110110111100100101001100111011", "1011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10110110111100100101001100111011", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "0000001000000000000000000000000", "0", @@ -4073,8 +6598,14 @@ "0000001000000000000000000000", "00000010000000000000000000000", "000000100000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "0000001000000000000000000000000", "00", @@ -4092,8 +6623,14 @@ "00000010000000000000000000", "0000001000000000000000000000", "000000100000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "0000001000000000000000000000000", "000", @@ -4106,8 +6643,14 @@ "000000100000000000000000", "000000100000000000000000000", "000000100000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "0000001000000000000000000000000", "0000", @@ -4117,41 +6660,83 @@ "00000010000000000000", "000000100000000000000000", "0000001000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "0000001000000000000000000000000", "00000010", "0000001000000000", "000000100000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "0000001000000000000000000000000", "0000001000", "00000010000000000000", "000000100000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "0000001000000000000000000000000", "00000010000", "0000001000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "0000001000000000000000000000000", "0000001000000000", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "0000001000000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "0000001000000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "00000001000000000000000000000001", "0", @@ -4185,8 +6770,14 @@ "00000001000000000000000000000", "000000010000000000000000000000", "0000000100000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "00000001000000000000000000000001", "00", @@ -4204,8 +6795,14 @@ "00000001000000000000000000", "0000000100000000000000000000", "000000010000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "00000001000000000000000000000001", "000", @@ -4218,8 +6815,14 @@ "000000010000000000000000", "000000010000000000000000000", "000000010000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "00000001000000000000000000000001", "0000", @@ -4229,42 +6832,84 @@ "00000001000000000000", "000000010000000000000000", "0000000100000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "00000001000000000000000000000001", "00000001", "0000000100000000", "000000010000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "00000001000000000000000000000001", "0000000100", "00000001000000000000", "000000010000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "00000001000000000000000000000001", "00000001000", "0000000100000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "00000001000000000000000000000001", "0000000100000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "00000001000000000000000000000001", "0000000100000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "00000001000000000000000000000001", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "10000001000000000000000000000000", "1", @@ -4298,8 +6943,14 @@ "10000001000000000000000000000", "100000010000000000000000000000", "1000000100000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "10000001000000000000000000000000", "10", @@ -4317,8 +6968,14 @@ "10000001000000000000000000", "1000000100000000000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "10000001000000000000000000000000", "100", @@ -4331,8 +6988,14 @@ "100000010000000000000000", "100000010000000000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "10000001000000000000000000000000", "1000", @@ -4342,42 +7005,84 @@ "10000001000000000000", "100000010000000000000000", "1000000100000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "10000001000000000000000000000000", "10000001", "1000000100000000", "100000010000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100", "10000001000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "10000001000000000000000000000000", "10000001000", "1000000100000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100000000", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100000000000000000000000", -}}, -{.value=16777216, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 16777216, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "10000001000000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000001000000000000000000000000", "1", @@ -4411,8 +7116,14 @@ "10000001000000000000000000000", "100000010000000000000000000000", "1000000100000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000001000000000000000000000000", "10", @@ -4430,8 +7141,14 @@ "10000001000000000000000000", "1000000100000000000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000001000000000000000000000000", "100", @@ -4444,8 +7161,14 @@ "100000010000000000000000", "100000010000000000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000001000000000000000000000000", "1000", @@ -4455,42 +7178,84 @@ "10000001000000000000", "100000010000000000000000", "1000000100000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000001000000000000000000000000", "10000001", "1000000100000000", "100000010000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100", "10000001000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000001000000000000000000000000", "10000001000", "1000000100000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000001000000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000001000000000000000000000000", "1", @@ -4524,8 +7289,14 @@ "10000001000000000000000000000", "100000010000000000000000000000", "1000000100000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000001000000000000000000000000", "10", @@ -4543,8 +7314,14 @@ "10000001000000000000000000", "1000000100000000000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000001000000000000000000000000", "100", @@ -4557,8 +7334,14 @@ "100000010000000000000000", "100000010000000000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000001000000000000000000000000", "1000", @@ -4568,42 +7351,84 @@ "10000001000000000000", "100000010000000000000000", "1000000100000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000001000000000000000000000000", "10000001", "1000000100000000", "100000010000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100", "10000001000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000001000000000000000000000000", "10000001000", "1000000100000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000001000000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "10000001000000000000000000000000", "1", @@ -4637,8 +7462,14 @@ "10000001000000000000000000000", "100000010000000000000000000000", "1000000100000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "10000001000000000000000000000000", "10", @@ -4656,8 +7487,14 @@ "10000001000000000000000000", "1000000100000000000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "10000001000000000000000000000000", "100", @@ -4670,8 +7507,14 @@ "100000010000000000000000", "100000010000000000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "10000001000000000000000000000000", "1000", @@ -4681,87 +7524,189 @@ "10000001000000000000", "100000010000000000000000", "1000000100000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "10000001000000000000000000000000", "10000001", "1000000100000000", "100000010000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100", "10000001000000000000", "100000010000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "10000001000000000000000000000000", "10000001000", "1000000100000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "10000001000000000000000000000000", "1000000100000000000000000000000", -}}, -{.value=16777216, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 16777216, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "10000001000000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "0000", "0", "00", "000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "0000", "00", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "0000", "000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(13), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "01111111111111111111111111111111", "0", @@ -4795,8 +7740,14 @@ "01111111111111111111111111111", "011111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "01111111111111111111111111111111", "01", @@ -4814,8 +7765,14 @@ "01111111111111111111111111", "0111111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "01111111111111111111111111111111", "011", @@ -4828,8 +7785,14 @@ "011111111111111111111111", "011111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "01111111111111111111111111111111", "0111", @@ -4839,42 +7802,84 @@ "01111111111111111111", "011111111111111111111111", "0111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111", "0111111111111111", "011111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111", "01111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111111", "0111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "01111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "000000", "0", @@ -4882,48 +7887,108 @@ "000", "0000", "00000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "000000", "00", "0000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "000000", "000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "000000", "0000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(32), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "01111111111111111111111111111111", "0", @@ -4957,8 +8022,14 @@ "01111111111111111111111111111", "011111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "01111111111111111111111111111111", "01", @@ -4976,8 +8047,14 @@ "01111111111111111111111111", "0111111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "01111111111111111111111111111111", "011", @@ -4990,8 +8067,14 @@ "011111111111111111111111", "011111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "01111111111111111111111111111111", "0111", @@ -5001,42 +8084,84 @@ "01111111111111111111", "011111111111111111111111", "0111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111", "0111111111111111", "011111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111", "01111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111111", "0111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "01111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000", "0", @@ -5049,8 +8174,14 @@ "00000000", "000000000", "0000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000", "00", @@ -5058,47 +8189,101 @@ "000000", "00000000", "0000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000", "000", "000000", "000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000", "0000", "00000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000", "00000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000", "0000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "01111111111111111111111111111111", "0", @@ -5132,8 +8317,14 @@ "01111111111111111111111111111", "011111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "01111111111111111111111111111111", "01", @@ -5151,8 +8342,14 @@ "01111111111111111111111111", "0111111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "01111111111111111111111111111111", "011", @@ -5165,8 +8362,14 @@ "011111111111111111111111", "011111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "01111111111111111111111111111111", "0111", @@ -5176,42 +8379,84 @@ "01111111111111111111", "011111111111111111111111", "0111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111", "0111111111111111", "011111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111", "01111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111111", "0111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "01111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000000000", "0", @@ -5245,8 +8490,14 @@ "00000000000000000000000000000", "000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000000000", "00", @@ -5264,8 +8515,14 @@ "00000000000000000000000000", "0000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000000000", "000", @@ -5278,8 +8535,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000000000", "0000", @@ -5289,42 +8552,84 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000", "00000000000000000000", "000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000000", "0000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "01111111111111111111111111111111", "0", @@ -5358,8 +8663,14 @@ "01111111111111111111111111111", "011111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "01111111111111111111111111111111", "01", @@ -5377,8 +8688,14 @@ "01111111111111111111111111", "0111111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "01111111111111111111111111111111", "011", @@ -5391,8 +8708,14 @@ "011111111111111111111111", "011111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "01111111111111111111111111111111", "0111", @@ -5402,42 +8725,84 @@ "01111111111111111111", "011111111111111111111111", "0111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111", "0111111111111111", "011111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111", "01111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111111", "0111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "01111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "01111111111111111111111111111111", "0", @@ -5471,8 +8836,14 @@ "01111111111111111111111111111", "011111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "01111111111111111111111111111111", "01", @@ -5490,8 +8861,14 @@ "01111111111111111111111111", "0111111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "01111111111111111111111111111111", "011", @@ -5504,8 +8881,14 @@ "011111111111111111111111", "011111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "01111111111111111111111111111111", "0111", @@ -5515,42 +8898,84 @@ "01111111111111111111", "011111111111111111111111", "0111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111", "0111111111111111", "011111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111", "01111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111111", "0111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "01111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "01111111111111111111111111111111", "0", @@ -5584,8 +9009,14 @@ "01111111111111111111111111111", "011111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "01111111111111111111111111111111", "01", @@ -5603,8 +9034,14 @@ "01111111111111111111111111", "0111111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "01111111111111111111111111111111", "011", @@ -5617,8 +9054,14 @@ "011111111111111111111111", "011111111111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "01111111111111111111111111111111", "0111", @@ -5628,42 +9071,84 @@ "01111111111111111111", "011111111111111111111111", "0111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111", "0111111111111111", "011111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111", "01111111111111111111", "011111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "01111111111111111111111111111111", "01111111111", "0111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "01111111111111111111111111111111", "0111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "01111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "1111111111111111111111111111111", "1", @@ -5696,8 +9181,14 @@ "1111111111111111111111111111", "11111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "1111111111111111111111111111111", "11", @@ -5715,8 +9206,14 @@ "11111111111111111111111111", "1111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "1111111111111111111111111111111", "111", @@ -5729,8 +9226,14 @@ "111111111111111111111111", "111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "1111111111111111111111111111111", "1111", @@ -5740,41 +9243,83 @@ "11111111111111111111", "111111111111111111111111", "1111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "1111111111111111111111111111111", "11111111", "1111111111111111", "111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "1111111111111111111111111111111", "1111111111", "11111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "1111111111111111111111111111111", "11111111111", "1111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "1111111111111111111111111111111", "1111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(0), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000000000000000000000000", "1", @@ -5808,8 +9353,14 @@ "10000000000000000000000000000", "100000000000000000000000000000", "1000000000000000000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000000000000000000000000", "10", @@ -5827,8 +9378,14 @@ "10000000000000000000000000", "1000000000000000000000000000", "100000000000000000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000000000000000000000000", "100", @@ -5841,8 +9398,14 @@ "100000000000000000000000", "100000000000000000000000000", "100000000000000000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000000000000000000000000", "1000", @@ -5852,42 +9415,84 @@ "10000000000000000000", "100000000000000000000000", "1000000000000000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000000000000000000000000", "10000000", "1000000000000000", "100000000000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000000000000000000000000", "1000000000", "10000000000000000000", "100000000000000000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000000000000000000000000", "10000000000", "1000000000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000000000000000000000000", "1000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000000000000000000000000", "1000000000000000000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(-1), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000000000000000000000000", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "11111111111111111111111111111111", "1", @@ -5921,8 +9526,14 @@ "11111111111111111111111111111", "111111111111111111111111111111", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "11111111111111111111111111111111", "11", @@ -5940,8 +9551,14 @@ "11111111111111111111111111", "1111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "11111111111111111111111111111111", "111", @@ -5954,8 +9571,14 @@ "111111111111111111111111", "111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "11111111111111111111111111111111", "1111", @@ -5965,42 +9588,84 @@ "11111111111111111111", "111111111111111111111111", "1111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "11111111111111111111111111111111", "11111111", "1111111111111111", "111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111", "11111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "11111111111111111111111111111111", "11111111111", "1111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = 2147483647, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "11111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "11111111111111111111111111111111", "1", @@ -6034,8 +9699,14 @@ "11111111111111111111111111111", "111111111111111111111111111111", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "11111111111111111111111111111111", "11", @@ -6053,8 +9724,14 @@ "11111111111111111111111111", "1111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "11111111111111111111111111111111", "111", @@ -6067,8 +9744,14 @@ "111111111111111111111111", "111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "11111111111111111111111111111111", "1111", @@ -6078,42 +9761,84 @@ "11111111111111111111", "111111111111111111111111", "1111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "11111111111111111111111111111111", "11111111", "1111111111111111", "111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111", "11111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "11111111111111111111111111111111", "11111111111", "1111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "11111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "11111111111111111111111111111111", "1", @@ -6147,8 +9872,14 @@ "11111111111111111111111111111", "111111111111111111111111111111", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "11111111111111111111111111111111", "11", @@ -6166,8 +9897,14 @@ "11111111111111111111111111", "1111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "11111111111111111111111111111111", "111", @@ -6180,8 +9917,14 @@ "111111111111111111111111", "111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "11111111111111111111111111111111", "1111", @@ -6191,42 +9934,84 @@ "11111111111111111111", "111111111111111111111111", "1111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "11111111111111111111111111111111", "11111111", "1111111111111111", "111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111", "11111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "11111111111111111111111111111111", "11111111111", "1111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "11111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "11111111111111111111111111111111", "1", @@ -6260,8 +10045,14 @@ "11111111111111111111111111111", "111111111111111111111111111111", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "11111111111111111111111111111111", "11", @@ -6279,8 +10070,14 @@ "11111111111111111111111111", "1111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "11111111111111111111111111111111", "111", @@ -6293,8 +10090,14 @@ "111111111111111111111111", "111111111111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "11111111111111111111111111111111", "1111", @@ -6304,42 +10107,84 @@ "11111111111111111111", "111111111111111111111111", "1111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "11111111111111111111111111111111", "11111111", "1111111111111111", "111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111", "11111111111111111111", "111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "11111111111111111111111111111111", "11111111111", "1111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "11111111111111111111111111111111", "1111111111111111111111111111111", -}}, -{.value=2147483647, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 2147483647, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "11111111111111111111111111111111", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=1, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000000000", "0", @@ -6373,8 +10218,14 @@ "00000000000000000000000000000", "000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=2, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000000000", "00", @@ -6392,8 +10243,14 @@ "00000000000000000000000000", "0000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=3, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000000000", "000", @@ -6406,8 +10263,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=4, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000000000", "0000", @@ -6417,42 +10280,84 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=8, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=10, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000", "00000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=11, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000000", "0000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=16, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=31, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(13), .sparsity=32, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=1, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000000000", "0", @@ -6486,8 +10391,14 @@ "00000000000000000000000000000", "000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=2, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000000000", "00", @@ -6505,8 +10416,14 @@ "00000000000000000000000000", "0000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=3, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000000000", "000", @@ -6519,8 +10436,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=4, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000000000", "0000", @@ -6530,42 +10453,84 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=8, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=10, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000", "00000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=11, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000000", "0000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=16, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=31, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(32), .sparsity=32, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=1, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000000000", "0", @@ -6599,8 +10564,14 @@ "00000000000000000000000000000", "000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=2, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000000000", "00", @@ -6618,8 +10589,14 @@ "00000000000000000000000000", "0000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=3, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000000000", "000", @@ -6632,8 +10609,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=4, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000000000", "0000", @@ -6643,42 +10626,84 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=8, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=10, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000", "00000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=11, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000000", "0000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=16, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=31, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(1024), .sparsity=32, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=1, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000000000", "0", @@ -6712,8 +10737,14 @@ "00000000000000000000000000000", "000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=2, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000000000", "00", @@ -6731,8 +10762,14 @@ "00000000000000000000000000", "0000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=3, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000000000", "000", @@ -6745,8 +10782,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=4, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000000000", "0000", @@ -6756,42 +10799,84 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=8, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=10, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000", "00000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=11, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000000", "0000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=16, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=31, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min=OPT_I32_C(INT32_MIN), .max=OPT_I32_C(2147483647), .sparsity=32, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = true, .value = INT32_MIN }, + .max = { .set = true, .value = 2147483647 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000000000", "0", @@ -6825,8 +10910,14 @@ "00000000000000000000000000000", "000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000000000", "00", @@ -6844,8 +10935,14 @@ "00000000000000000000000000", "0000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000000000", "000", @@ -6858,8 +10955,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000000000", "0000", @@ -6869,38 +10972,75 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000", "00000000000000000000", "000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000000000", "00000000000", "0000000000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=INT32_MIN, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = INT32_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000000000", -}}, + }, +}, diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_int64.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_int64.cstruct index 957e8a8..a75d556 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_int64.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-edge-generation/edges_int64.cstruct @@ -1,96 +1,221 @@ -// This is a copy of test vectors from the mongodb/mongo repository. -// The order of edges is rearranged to permit exact matching. -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=1, { +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` +// clang-format off +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "0111", "0", "01", "011", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "0111", "01", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "0111", "011", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(13), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "0111", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "1000", "1", "10", "100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "1000", "10", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "1000", "100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "1000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1", @@ -156,8 +281,14 @@ "1000000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10", @@ -191,8 +322,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "100", @@ -216,8 +353,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000", @@ -235,8 +378,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000", @@ -246,8 +395,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000", @@ -256,8 +411,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000", @@ -265,26 +426,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "000111", "0", @@ -292,48 +477,108 @@ "000", "0001", "00011", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "000111", "00", "0001", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "000111", "000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "000111", "0001", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "000111", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "001000", "0", @@ -341,48 +586,108 @@ "001", "0010", "00100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "001000", "00", "0010", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "001000", "001", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "001000", "0010", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "001000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1", @@ -448,8 +753,14 @@ "1000000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10", @@ -483,8 +794,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "100", @@ -508,8 +825,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000", @@ -527,8 +850,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000", @@ -538,8 +867,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000", @@ -548,8 +883,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000", @@ -557,26 +898,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000000111", "0", @@ -589,8 +954,14 @@ "00000000", "000000001", "0000000011", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000000111", "00", @@ -598,47 +969,101 @@ "000000", "00000000", "0000000011", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000000111", "000", "000000", "000000001", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000000111", "0000", "00000000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000000111", "00000000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000000111", "0000000011", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000000111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000000111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000000111", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000000111", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000001000", "0", @@ -651,8 +1076,14 @@ "00000001", "000000010", "0000000100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000001000", "00", @@ -660,47 +1091,101 @@ "000000", "00000001", "0000000100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000001000", "000", "000000", "000000010", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000001000", "0000", "00000001", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000001000", "00000001", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000001000", "0000000100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000001000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000001000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000001000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000001000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1", @@ -766,8 +1251,14 @@ "1000000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10", @@ -801,8 +1292,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "100", @@ -826,8 +1323,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000", @@ -845,8 +1348,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000", @@ -856,8 +1365,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000", @@ -866,8 +1381,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000", @@ -875,26 +1396,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000000111", "0", @@ -928,8 +1473,14 @@ "00000000000000000000000000000", "000000000000000000000000000001", "0000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000000111", "00", @@ -947,8 +1498,14 @@ "00000000000000000000000000", "0000000000000000000000000000", "000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000000111", "000", @@ -961,8 +1518,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000000111", "0000", @@ -972,42 +1535,84 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000000111", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000000111", "0000000000", "00000000000000000000", "000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000000111", "00000000000", "0000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000000111", "0000000000000000", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000000111", "0000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000000111", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "000000000000000000000000000001000", "0", @@ -1042,8 +1647,14 @@ "000000000000000000000000000001", "0000000000000000000000000000010", "00000000000000000000000000000100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "000000000000000000000000000001000", "00", @@ -1062,8 +1673,14 @@ "0000000000000000000000000000", "000000000000000000000000000001", "00000000000000000000000000000100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "000000000000000000000000000001000", "000", @@ -1076,8 +1693,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "000000000000000000000000000001000", "0000", @@ -1088,45 +1711,87 @@ "000000000000000000000000", "0000000000000000000000000000", "00000000000000000000000000000100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "000000000000000000000000000001000", "00000000", "0000000000000000", "000000000000000000000000", "00000000000000000000000000000100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "000000000000000000000000000001000", "0000000000", "00000000000000000000", "000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "000000000000000000000000000001000", "00000000000", "0000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "000000000000000000000000000001000", "0000000000000000", "00000000000000000000000000000100", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "000000000000000000000000000001000", "0000000000000000000000000000010", -}}, -{.value=7, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "000000000000000000000000000001000", "00000000000000000000000000000100", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1", @@ -1192,8 +1857,14 @@ "1000000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10", @@ -1227,8 +1898,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "100", @@ -1252,8 +1929,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000", @@ -1271,8 +1954,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000", @@ -1282,8 +1971,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000", @@ -1292,8 +1987,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000", @@ -1301,26 +2002,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1", @@ -1386,8 +2111,14 @@ "1000000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10", @@ -1421,8 +2152,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "100", @@ -1446,8 +2183,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000", @@ -1465,8 +2208,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000", @@ -1476,8 +2225,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000", @@ -1486,8 +2241,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000", @@ -1495,26 +2256,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1", @@ -1580,8 +2365,14 @@ "1000000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10", @@ -1615,8 +2406,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "100", @@ -1640,8 +2437,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000", @@ -1659,8 +2462,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000", @@ -1670,8 +2479,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000", @@ -1680,8 +2495,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000", @@ -1689,26 +2510,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1", @@ -1774,8 +2619,14 @@ "1000000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10", @@ -1809,8 +2660,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "100", @@ -1834,8 +2691,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000011", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000", @@ -1853,8 +2716,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000", @@ -1864,8 +2733,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000", @@ -1874,8 +2749,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000", @@ -1883,26 +2764,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000000001", -}}, -{.value=7, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 7, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000000111", "10000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "100000", "1", @@ -1910,48 +2815,108 @@ "100", "1000", "10000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "100000", "10", "1000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "100000", "100", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "100000", "1000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(32), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "100000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "100001", "1", @@ -1959,48 +2924,108 @@ "100", "1000", "10000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "100001", "10", "1000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "100001", "100", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "100001", "1000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "100001", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1", @@ -2066,8 +3091,14 @@ "1000000000000000000000000000000000000000000000000000000000100", "10000000000000000000000000000000000000000000000000000000001000", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10", @@ -2101,8 +3132,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "100", @@ -2126,8 +3163,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000", @@ -2145,8 +3188,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000", @@ -2156,8 +3205,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000", @@ -2166,8 +3221,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000", @@ -2175,26 +3236,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000100000", "0", @@ -2207,8 +3292,14 @@ "00000100", "000001000", "0000010000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000100000", "00", @@ -2216,47 +3307,101 @@ "000001", "00000100", "0000010000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000100000", "000", "000001", "000001000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000100000", "0000", "00000100", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000100000", "00000100", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000100000", "0000010000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000100000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000100000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000100000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000100000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000100001", "0", @@ -2269,8 +3414,14 @@ "00000100", "000001000", "0000010000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000100001", "00", @@ -2278,47 +3429,101 @@ "000001", "00000100", "0000010000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000100001", "000", "000001", "000001000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000100001", "0000", "00000100", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000100001", "00000100", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000100001", "0000010000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000100001", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000100001", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000100001", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000100001", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1", @@ -2384,8 +3589,14 @@ "1000000000000000000000000000000000000000000000000000000000100", "10000000000000000000000000000000000000000000000000000000001000", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10", @@ -2419,8 +3630,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "100", @@ -2444,8 +3661,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000", @@ -2463,8 +3686,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000", @@ -2474,8 +3703,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000", @@ -2484,8 +3719,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000", @@ -2493,26 +3734,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000000000100000", "0", @@ -2546,8 +3811,14 @@ "00000000000000000000000000100", "000000000000000000000000001000", "0000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000000000100000", "00", @@ -2565,8 +3836,14 @@ "00000000000000000000000000", "0000000000000000000000000010", "000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000000000100000", "000", @@ -2579,8 +3856,14 @@ "000000000000000000000000", "000000000000000000000000001", "000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000000000100000", "0000", @@ -2590,42 +3873,84 @@ "00000000000000000000", "000000000000000000000000", "0000000000000000000000000010", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000000000100000", "00000000", "0000000000000000", "000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000000000100000", "0000000000", "00000000000000000000", "000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000000000100000", "00000000000", "0000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000000000100000", "0000000000000000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000000000100000", "0000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000000000100000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "000000000000000000000000000100001", "0", @@ -2660,8 +3985,14 @@ "000000000000000000000000000100", "0000000000000000000000000001000", "00000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "000000000000000000000000000100001", "00", @@ -2680,8 +4011,14 @@ "0000000000000000000000000001", "000000000000000000000000000100", "00000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "000000000000000000000000000100001", "000", @@ -2694,8 +4031,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000100", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "000000000000000000000000000100001", "0000", @@ -2706,45 +4049,87 @@ "000000000000000000000000", "0000000000000000000000000001", "00000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "000000000000000000000000000100001", "00000000", "0000000000000000", "000000000000000000000000", "00000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "000000000000000000000000000100001", "0000000000", "00000000000000000000", "000000000000000000000000000100", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "000000000000000000000000000100001", "00000000000", "0000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "000000000000000000000000000100001", "0000000000000000", "00000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "000000000000000000000000000100001", "0000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "000000000000000000000000000100001", "00000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1", @@ -2810,8 +4195,14 @@ "1000000000000000000000000000000000000000000000000000000000100", "10000000000000000000000000000000000000000000000000000000001000", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10", @@ -2845,8 +4236,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "100", @@ -2870,8 +4267,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000", @@ -2889,8 +4292,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000", @@ -2900,8 +4309,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000", @@ -2910,8 +4325,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000", @@ -2919,26 +4340,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1", @@ -3004,8 +4449,14 @@ "1000000000000000000000000000000000000000000000000000000000100", "10000000000000000000000000000000000000000000000000000000001000", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10", @@ -3039,8 +4490,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "100", @@ -3064,8 +4521,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000", @@ -3083,8 +4546,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000", @@ -3094,8 +4563,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000", @@ -3104,8 +4579,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000", @@ -3113,26 +4594,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1", @@ -3198,8 +4703,14 @@ "1000000000000000000000000000000000000000000000000000000000100", "10000000000000000000000000000000000000000000000000000000001000", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10", @@ -3233,8 +4744,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "100", @@ -3258,8 +4775,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000", @@ -3277,8 +4800,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000", @@ -3288,8 +4817,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000", @@ -3298,8 +4833,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000", @@ -3307,26 +4848,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1", @@ -3392,8 +4957,14 @@ "1000000000000000000000000000000000000000000000000000000000100", "10000000000000000000000000000000000000000000000000000000001000", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10", @@ -3427,8 +4998,14 @@ "1000000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "100", @@ -3452,8 +5029,14 @@ "100000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", "100000000000000000000000000000000000000000000000000000000010000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000", @@ -3471,8 +5054,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000", @@ -3482,8 +5071,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000", @@ -3492,8 +5087,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000000010", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000", @@ -3501,26 +5102,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000000001000", -}}, -{.value=32, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 32, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000000000100000", "10000000000000000000000000000000", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "01111111111", "0", @@ -3533,8 +5158,14 @@ "01111111", "011111111", "0111111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "01111111111", "01", @@ -3542,47 +5173,101 @@ "011111", "01111111", "0111111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "01111111111", "011", "011111", "011111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "01111111111", "0111", "01111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "01111111111", "01111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "01111111111", "0111111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "01111111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "01111111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "01111111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "01111111111", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "10000000000", "1", @@ -3595,8 +5280,14 @@ "10000000", "100000000", "1000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "10000000000", "10", @@ -3604,47 +5295,101 @@ "100000", "10000000", "1000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "10000000000", "100", "100000", "100000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "10000000000", "1000", "10000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "10000000000", "10000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "10000000000", "1000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "10000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "10000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "10000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "10000000000", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1", @@ -3710,8 +5455,14 @@ "1000000000000000000000000000000000000000000000000000001111111", "10000000000000000000000000000000000000000000000000000011111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10", @@ -3745,8 +5496,14 @@ "1000000000000000000000000000000000000000000000000000001111", "100000000000000000000000000000000000000000000000000000111111", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "100", @@ -3770,8 +5527,14 @@ "100000000000000000000000000000000000000000000000000000111", "100000000000000000000000000000000000000000000000000000111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000", @@ -3789,8 +5552,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000", @@ -3800,8 +5569,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000", @@ -3810,8 +5585,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000", @@ -3819,26 +5600,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000001", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000000000000000000000000", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000000000000001111111111", "0", @@ -3872,8 +5677,14 @@ "00000000000000000000001111111", "000000000000000000000011111111", "0000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000000000000001111111111", "00", @@ -3891,8 +5702,14 @@ "00000000000000000000001111", "0000000000000000000000111111", "000000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000000000000001111111111", "000", @@ -3905,8 +5722,14 @@ "000000000000000000000011", "000000000000000000000011111", "000000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000000000000001111111111", "0000", @@ -3916,42 +5739,84 @@ "00000000000000000000", "000000000000000000000011", "0000000000000000000000111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000000000000001111111111", "00000000", "0000000000000000", "000000000000000000000011", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000000000000001111111111", "0000000000", "00000000000000000000", "000000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000000000000001111111111", "00000000000", "0000000000000000000000", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000000000000001111111111", "0000000000000000", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000000000000001111111111", "0000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000000000000001111111111", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "000000000000000000000010000000000", "0", @@ -3986,8 +5851,14 @@ "000000000000000000000010000000", "0000000000000000000000100000000", "00000000000000000000001000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "000000000000000000000010000000000", "00", @@ -4006,8 +5877,14 @@ "0000000000000000000000100000", "000000000000000000000010000000", "00000000000000000000001000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "000000000000000000000010000000000", "000", @@ -4020,8 +5897,14 @@ "000000000000000000000010", "000000000000000000000010000", "000000000000000000000010000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "000000000000000000000010000000000", "0000", @@ -4032,45 +5915,87 @@ "000000000000000000000010", "0000000000000000000000100000", "00000000000000000000001000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "000000000000000000000010000000000", "00000000", "0000000000000000", "000000000000000000000010", "00000000000000000000001000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "000000000000000000000010000000000", "0000000000", "00000000000000000000", "000000000000000000000010000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "000000000000000000000010000000000", "00000000000", "0000000000000000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "000000000000000000000010000000000", "0000000000000000", "00000000000000000000001000000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "000000000000000000000010000000000", "0000000000000000000000100000000", -}}, -{.value=1023, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "000000000000000000000010000000000", "00000000000000000000001000000000", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1", @@ -4136,8 +6061,14 @@ "1000000000000000000000000000000000000000000000000000001111111", "10000000000000000000000000000000000000000000000000000011111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10", @@ -4171,8 +6102,14 @@ "1000000000000000000000000000000000000000000000000000001111", "100000000000000000000000000000000000000000000000000000111111", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "100", @@ -4196,8 +6133,14 @@ "100000000000000000000000000000000000000000000000000000111", "100000000000000000000000000000000000000000000000000000111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000", @@ -4215,8 +6158,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000", @@ -4226,8 +6175,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000", @@ -4236,8 +6191,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000", @@ -4245,26 +6206,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000001", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000000000000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1", @@ -4330,8 +6315,14 @@ "1000000000000000000000000000000000000000000000000000001111111", "10000000000000000000000000000000000000000000000000000011111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10", @@ -4365,8 +6356,14 @@ "1000000000000000000000000000000000000000000000000000001111", "100000000000000000000000000000000000000000000000000000111111", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "100", @@ -4390,8 +6387,14 @@ "100000000000000000000000000000000000000000000000000000111", "100000000000000000000000000000000000000000000000000000111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000", @@ -4409,8 +6412,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000", @@ -4420,8 +6429,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000", @@ -4430,8 +6445,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000", @@ -4439,26 +6460,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000001", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000000000000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1", @@ -4524,8 +6569,14 @@ "1000000000000000000000000000000000000000000000000000001111111", "10000000000000000000000000000000000000000000000000000011111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10", @@ -4559,8 +6610,14 @@ "1000000000000000000000000000000000000000000000000000001111", "100000000000000000000000000000000000000000000000000000111111", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "100", @@ -4584,8 +6641,14 @@ "100000000000000000000000000000000000000000000000000000111", "100000000000000000000000000000000000000000000000000000111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000", @@ -4603,8 +6666,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000", @@ -4614,8 +6683,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000", @@ -4624,8 +6699,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000", @@ -4633,26 +6714,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000001", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000000000000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1", @@ -4718,8 +6823,14 @@ "1000000000000000000000000000000000000000000000000000001111111", "10000000000000000000000000000000000000000000000000000011111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10", @@ -4753,8 +6864,14 @@ "1000000000000000000000000000000000000000000000000000001111", "100000000000000000000000000000000000000000000000000000111111", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "100", @@ -4778,8 +6895,14 @@ "100000000000000000000000000000000000000000000000000000111", "100000000000000000000000000000000000000000000000000000111111", "100000000000000000000000000000000000000000000000000000111111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000", @@ -4797,8 +6920,14 @@ "1000000000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000", @@ -4808,8 +6937,14 @@ "1000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000", @@ -4818,8 +6953,14 @@ "1000000000000000000000000000000000000000", "10000000000000000000000000000000000000000000000000", "100000000000000000000000000000000000000000000000000000111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000", @@ -4827,26 +6968,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000001", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000000000000000000", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "1000000000000000000000000000000", "10000000000000000000000000000000000000000000000000000011111111", -}}, -{.value=1023, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 1023, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000000000000000000000001111111111", "10000000000000000000000000000000", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "00110110111100100101001100111011", "0", @@ -4880,8 +7045,14 @@ "00110110111100100101001100111", "001101101111001001010011001110", "0011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "00110110111100100101001100111011", "00", @@ -4899,8 +7070,14 @@ "00110110111100100101001100", "0011011011110010010100110011", "001101101111001001010011001110", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "00110110111100100101001100111011", "001", @@ -4913,8 +7090,14 @@ "001101101111001001010011", "001101101111001001010011001", "001101101111001001010011001110", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "00110110111100100101001100111011", "0011", @@ -4924,42 +7107,84 @@ "00110110111100100101", "001101101111001001010011", "0011011011110010010100110011", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "00110110111100100101001100111011", "00110110", "0011011011110010", "001101101111001001010011", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "00110110111100100101001100111011", "0011011011", "00110110111100100101", "001101101111001001010011001110", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "00110110111100100101001100111011", "00110110111", "0011011011110010010100", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "00110110111100100101001100111011", "0011011011110010", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "00110110111100100101001100111011", "0011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I64_C(0), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = 0 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "00110110111100100101001100111011", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "000110110111100100101001100111100", "0", @@ -4994,8 +7219,14 @@ "000110110111100100101001100111", "0001101101111001001010011001111", "00011011011110010010100110011110", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "000110110111100100101001100111100", "00", @@ -5014,8 +7245,14 @@ "0001101101111001001010011001", "000110110111100100101001100111", "00011011011110010010100110011110", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "000110110111100100101001100111100", "000", @@ -5028,8 +7265,14 @@ "000110110111100100101001", "000110110111100100101001100", "000110110111100100101001100111", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "000110110111100100101001100111100", "0001", @@ -5040,45 +7283,87 @@ "000110110111100100101001", "0001101101111001001010011001", "00011011011110010010100110011110", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "000110110111100100101001100111100", "00011011", "0001101101111001", "000110110111100100101001", "00011011011110010010100110011110", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "000110110111100100101001100111100", "0001101101", "00011011011110010010", "000110110111100100101001100111", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "000110110111100100101001100111100", "00011011011", "0001101101111001001010", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "000110110111100100101001100111100", "0001101101111001", "00011011011110010010100110011110", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "000110110111100100101001100111100", "0001101101111001001010011001111", -}}, -{.value=921850683, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "000110110111100100101001100111100", "00011011011110010010100110011110", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1", @@ -5144,8 +7429,14 @@ "1000000000000000000000000000000000110110111100100101001100111", "10000000000000000000000000000000001101101111001001010011001110", "100000000000000000000000000000000011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10", @@ -5179,8 +7470,14 @@ "1000000000000000000000000000000000110110111100100101001100", "100000000000000000000000000000000011011011110010010100110011", "10000000000000000000000000000000001101101111001001010011001110", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "100", @@ -5204,8 +7501,14 @@ "100000000000000000000000000000000011011011110010010100110", "100000000000000000000000000000000011011011110010010100110011", "100000000000000000000000000000000011011011110010010100110011101", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000", @@ -5223,8 +7526,14 @@ "1000000000000000000000000000000000110110111100100101", "10000000000000000000000000000000001101101111001001010011", "100000000000000000000000000000000011011011110010010100110011", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000", @@ -5234,8 +7543,14 @@ "1000000000000000000000000000000000110110", "100000000000000000000000000000000011011011110010", "10000000000000000000000000000000001101101111001001010011", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000", @@ -5244,8 +7559,14 @@ "1000000000000000000000000000000000110110", "10000000000000000000000000000000001101101111001001", "100000000000000000000000000000000011011011110010010100110011", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000000", @@ -5253,26 +7574,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000001101101111", "1000000000000000000000000000000000110110111100100101001", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000011011011110010", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000000000000000000000000", "10000000000000000000000000000000001101101111001001010011001110", -}}, -{.value=921850683, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000000000000000000000000000", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1", @@ -5338,8 +7683,14 @@ "1000000000000000000000000000000000110110111100100101001100111", "10000000000000000000000000000000001101101111001001010011001110", "100000000000000000000000000000000011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10", @@ -5373,8 +7724,14 @@ "1000000000000000000000000000000000110110111100100101001100", "100000000000000000000000000000000011011011110010010100110011", "10000000000000000000000000000000001101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "100", @@ -5398,8 +7755,14 @@ "100000000000000000000000000000000011011011110010010100110", "100000000000000000000000000000000011011011110010010100110011", "100000000000000000000000000000000011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000", @@ -5417,8 +7780,14 @@ "1000000000000000000000000000000000110110111100100101", "10000000000000000000000000000000001101101111001001010011", "100000000000000000000000000000000011011011110010010100110011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000", @@ -5428,8 +7797,14 @@ "1000000000000000000000000000000000110110", "100000000000000000000000000000000011011011110010", "10000000000000000000000000000000001101101111001001010011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000", @@ -5438,8 +7813,14 @@ "1000000000000000000000000000000000110110", "10000000000000000000000000000000001101101111001001", "100000000000000000000000000000000011011011110010010100110011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000000", @@ -5447,26 +7828,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000001101101111", "1000000000000000000000000000000000110110111100100101001", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000011011011110010", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000000000000000000000000", "10000000000000000000000000000000001101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000000000000000000000000000", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1", @@ -5532,8 +7937,14 @@ "1000000000000000000000000000000000110110111100100101001100111", "10000000000000000000000000000000001101101111001001010011001110", "100000000000000000000000000000000011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10", @@ -5567,8 +7978,14 @@ "1000000000000000000000000000000000110110111100100101001100", "100000000000000000000000000000000011011011110010010100110011", "10000000000000000000000000000000001101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "100", @@ -5592,8 +8009,14 @@ "100000000000000000000000000000000011011011110010010100110", "100000000000000000000000000000000011011011110010010100110011", "100000000000000000000000000000000011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000", @@ -5611,8 +8034,14 @@ "1000000000000000000000000000000000110110111100100101", "10000000000000000000000000000000001101101111001001010011", "100000000000000000000000000000000011011011110010010100110011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000", @@ -5622,8 +8051,14 @@ "1000000000000000000000000000000000110110", "100000000000000000000000000000000011011011110010", "10000000000000000000000000000000001101101111001001010011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000", @@ -5632,8 +8067,14 @@ "1000000000000000000000000000000000110110", "10000000000000000000000000000000001101101111001001", "100000000000000000000000000000000011011011110010010100110011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000000", @@ -5641,26 +8082,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000001101101111", "1000000000000000000000000000000000110110111100100101001", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000011011011110010", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000000000000000000000000", "10000000000000000000000000000000001101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000000000000000000000000000", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1", @@ -5726,8 +8191,14 @@ "1000000000000000000000000000000000110110111100100101001100111", "10000000000000000000000000000000001101101111001001010011001110", "100000000000000000000000000000000011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10", @@ -5761,8 +8232,14 @@ "1000000000000000000000000000000000110110111100100101001100", "100000000000000000000000000000000011011011110010010100110011", "10000000000000000000000000000000001101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "100", @@ -5786,8 +8263,14 @@ "100000000000000000000000000000000011011011110010010100110", "100000000000000000000000000000000011011011110010010100110011", "100000000000000000000000000000000011011011110010010100110011101", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000", @@ -5805,8 +8288,14 @@ "1000000000000000000000000000000000110110111100100101", "10000000000000000000000000000000001101101111001001010011", "100000000000000000000000000000000011011011110010010100110011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000", @@ -5816,8 +8305,14 @@ "1000000000000000000000000000000000110110", "100000000000000000000000000000000011011011110010", "10000000000000000000000000000000001101101111001001010011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000", @@ -5826,8 +8321,14 @@ "1000000000000000000000000000000000110110", "10000000000000000000000000000000001101101111001001", "100000000000000000000000000000000011011011110010010100110011", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000000", @@ -5835,26 +8336,50 @@ "100000000000000000000000000000000", "10000000000000000000000000000000001101101111", "1000000000000000000000000000000000110110111100100101001", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000000000", "10000000000000000000000000000000", "100000000000000000000000000000000011011011110010", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "1000000000000000000000000000000", "10000000000000000000000000000000001101101111001001010011001110", -}}, -{.value=921850683, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 921850683, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1000000000000000000000000000000000110110111100100101001100111011", "10000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1", @@ -5920,8 +8445,14 @@ "1001000000000000000000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10", @@ -5955,8 +8486,14 @@ "1001000000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "100", @@ -5980,8 +8517,14 @@ "100100000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001", @@ -5999,8 +8542,14 @@ "1001000000000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10010000", @@ -6010,8 +8559,14 @@ "1001000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001000000", @@ -6020,8 +8575,14 @@ "1001000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10010000000", @@ -6029,26 +8590,50 @@ "100100000000000000000000000000000", "10010000000000000000000000000000000000000000", "1001000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001000000000000", "10010000000000000000000000000000", "100100000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10010000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1", @@ -6114,8 +8699,14 @@ "1001000000000000000000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10", @@ -6149,8 +8740,14 @@ "1001000000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "100", @@ -6174,8 +8771,14 @@ "100100000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001", @@ -6193,8 +8796,14 @@ "1001000000000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10010000", @@ -6204,8 +8813,14 @@ "1001000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001000000", @@ -6214,8 +8829,14 @@ "1001000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10010000000", @@ -6223,26 +8844,50 @@ "100100000000000000000000000000000", "10010000000000000000000000000000000000000000", "1001000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001000000000000", "10010000000000000000000000000000", "100100000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10010000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1", @@ -6308,8 +8953,14 @@ "1001000000000000000000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10", @@ -6343,8 +8994,14 @@ "1001000000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "100", @@ -6368,8 +9025,14 @@ "100100000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001", @@ -6387,8 +9050,14 @@ "1001000000000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10010000", @@ -6398,8 +9067,14 @@ "1001000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001000000", @@ -6408,8 +9083,14 @@ "1001000000000000000000000000000000000000", "10010000000000000000000000000000000000000000000000", "100100000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10010000000", @@ -6417,71 +9098,155 @@ "100100000000000000000000000000000", "10010000000000000000000000000000000000000000", "1001000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001000000000000", "10010000000000000000000000000000", "100100000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "1001000000000000000000000000000", "10010000000000000000000000000000000000000000000000000000000000", -}}, -{.value=1152921504606846976, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 1152921504606846976, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1001000000000000000000000000000000000000000000000000000000000000", "10010000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "0000", "0", "00", "000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "0000", "00", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "0000", "000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(13), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "0000", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0", @@ -6547,8 +9312,14 @@ "0111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01", @@ -6582,8 +9353,14 @@ "0111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "011", @@ -6607,8 +9384,14 @@ "011111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111", @@ -6626,8 +9409,14 @@ "0111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111", @@ -6637,8 +9426,14 @@ "0111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111", @@ -6647,8 +9442,14 @@ "0111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111", @@ -6656,26 +9457,50 @@ "011111111111111111111111111111111", "01111111111111111111111111111111111111111111", "0111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111", "01111111111111111111111111111111", "011111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "000000", "0", @@ -6683,48 +9508,108 @@ "000", "0000", "00000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "000000", "00", "0000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "000000", "000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "000000", "0000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(32), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "000000", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0", @@ -6790,8 +9675,14 @@ "0111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01", @@ -6825,8 +9716,14 @@ "0111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "011", @@ -6850,8 +9747,14 @@ "011111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111", @@ -6869,8 +9772,14 @@ "0111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111", @@ -6880,8 +9789,14 @@ "0111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111", @@ -6890,8 +9805,14 @@ "0111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111", @@ -6899,26 +9820,50 @@ "011111111111111111111111111111111", "01111111111111111111111111111111111111111111", "0111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111", "01111111111111111111111111111111", "011111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "00000000000", "0", @@ -6931,8 +9876,14 @@ "00000000", "000000000", "0000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "00000000000", "00", @@ -6940,47 +9891,101 @@ "000000", "00000000", "0000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "00000000000", "000", "000000", "000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "00000000000", "0000", "00000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "00000000000", "00000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "00000000000", "0000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "00000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "00000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "00000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "00000000000", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0", @@ -7046,8 +10051,14 @@ "0111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01", @@ -7081,8 +10092,14 @@ "0111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "011", @@ -7106,8 +10123,14 @@ "011111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111", @@ -7125,8 +10148,14 @@ "0111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111", @@ -7136,8 +10165,14 @@ "0111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111", @@ -7146,8 +10181,14 @@ "0111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111", @@ -7155,26 +10196,50 @@ "011111111111111111111111111111111", "01111111111111111111111111111111111111111111", "0111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111", "01111111111111111111111111111111", "011111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "000000000000000000000000000000000", "0", @@ -7209,8 +10274,14 @@ "000000000000000000000000000000", "0000000000000000000000000000000", "00000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "000000000000000000000000000000000", "00", @@ -7229,8 +10300,14 @@ "0000000000000000000000000000", "000000000000000000000000000000", "00000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "000000000000000000000000000000000", "000", @@ -7243,8 +10320,14 @@ "000000000000000000000000", "000000000000000000000000000", "000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "000000000000000000000000000000000", "0000", @@ -7255,45 +10338,87 @@ "000000000000000000000000", "0000000000000000000000000000", "00000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "000000000000000000000000000000000", "00000000", "0000000000000000", "000000000000000000000000", "00000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "000000000000000000000000000000000", "0000000000", "00000000000000000000", "000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "000000000000000000000000000000000", "00000000000", "0000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "000000000000000000000000000000000", "0000000000000000", "00000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "000000000000000000000000000000000", "0000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(-1), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = -1 }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "000000000000000000000000000000000", "00000000000000000000000000000000", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0", @@ -7359,8 +10484,14 @@ "0111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01", @@ -7394,8 +10525,14 @@ "0111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "011", @@ -7419,8 +10556,14 @@ "011111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111", @@ -7438,8 +10581,14 @@ "0111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111", @@ -7449,8 +10598,14 @@ "0111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111", @@ -7459,8 +10614,14 @@ "0111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111", @@ -7468,26 +10629,50 @@ "011111111111111111111111111111111", "01111111111111111111111111111111111111111111", "0111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111", "01111111111111111111111111111111", "011111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0", @@ -7553,8 +10738,14 @@ "0111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01", @@ -7588,8 +10779,14 @@ "0111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "011", @@ -7613,8 +10810,14 @@ "011111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111", @@ -7632,8 +10835,14 @@ "0111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111", @@ -7643,8 +10852,14 @@ "0111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111", @@ -7653,8 +10868,14 @@ "0111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111", @@ -7662,26 +10883,50 @@ "011111111111111111111111111111111", "01111111111111111111111111111111111111111111", "0111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111", "01111111111111111111111111111111", "011111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0", @@ -7747,8 +10992,14 @@ "0111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01", @@ -7782,8 +11033,14 @@ "0111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "011", @@ -7807,8 +11064,14 @@ "011111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111", @@ -7826,8 +11089,14 @@ "0111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111", @@ -7837,8 +11106,14 @@ "0111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111", @@ -7847,8 +11122,14 @@ "0111111111111111111111111111111111111111", "01111111111111111111111111111111111111111111111111", "011111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111", @@ -7856,26 +11137,50 @@ "011111111111111111111111111111111", "01111111111111111111111111111111111111111111", "0111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111", "01111111111111111111111111111111", "011111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "0111111111111111111111111111111", "01111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=-1, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = -1, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "0111111111111111111111111111111111111111111111111111111111111111", "01111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1", @@ -7941,8 +11246,14 @@ "1111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11", @@ -7976,8 +11287,14 @@ "1111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "111", @@ -8001,8 +11318,14 @@ "111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111", @@ -8020,8 +11343,14 @@ "1111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11111111", @@ -8031,8 +11360,14 @@ "1111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111", @@ -8041,8 +11376,14 @@ "1111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11111111111", @@ -8050,26 +11391,50 @@ "111111111111111111111111111111111", "11111111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111", "11111111111111111111111111111111", "111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1", @@ -8135,8 +11500,14 @@ "1111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11", @@ -8170,8 +11541,14 @@ "1111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "111", @@ -8195,8 +11572,14 @@ "111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111", @@ -8214,8 +11597,14 @@ "1111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11111111", @@ -8225,8 +11614,14 @@ "1111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111", @@ -8235,8 +11630,14 @@ "1111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11111111111", @@ -8244,26 +11645,50 @@ "111111111111111111111111111111111", "11111111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111", "11111111111111111111111111111111", "111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1", @@ -8329,8 +11754,14 @@ "1111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11", @@ -8364,8 +11795,14 @@ "1111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "111", @@ -8389,8 +11826,14 @@ "111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111", @@ -8408,8 +11851,14 @@ "1111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11111111", @@ -8419,8 +11868,14 @@ "1111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111", @@ -8429,8 +11884,14 @@ "1111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111", "111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11111111111", @@ -8438,26 +11899,50 @@ "111111111111111111111111111111111", "11111111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111", "11111111111111111111111111111111", "111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111", -}}, -{.value=9223372036854775807, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = 9223372036854775807, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "1111111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=1, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 1, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0", @@ -8523,8 +12008,14 @@ "0000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=2, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 2, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00", @@ -8558,8 +12049,14 @@ "0000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=3, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 3, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "000", @@ -8583,8 +12080,14 @@ "000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=4, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 4, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000", @@ -8602,8 +12105,14 @@ "0000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=8, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 8, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000", @@ -8613,8 +12122,14 @@ "0000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=10, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 10, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000", @@ -8623,8 +12138,14 @@ "0000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=11, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 11, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000", @@ -8632,26 +12153,50 @@ "000000000000000000000000000000000", "00000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=16, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 16, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000", "00000000000000000000000000000000", "000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=31, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 31, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(13), .sparsity=32, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 13 }, + .sparsity = 32, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=1, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 1, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0", @@ -8717,8 +12262,14 @@ "0000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=2, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 2, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00", @@ -8752,8 +12303,14 @@ "0000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=3, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 3, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "000", @@ -8777,8 +12334,14 @@ "000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=4, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 4, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000", @@ -8796,8 +12359,14 @@ "0000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=8, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 8, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000", @@ -8807,8 +12376,14 @@ "0000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=10, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 10, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000", @@ -8817,8 +12392,14 @@ "0000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=11, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 11, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000", @@ -8826,26 +12407,50 @@ "000000000000000000000000000000000", "00000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=16, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 16, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000", "00000000000000000000000000000000", "000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=31, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 31, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(32), .sparsity=32, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 32 }, + .sparsity = 32, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=1, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 1, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0", @@ -8911,8 +12516,14 @@ "0000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=2, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 2, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00", @@ -8946,8 +12557,14 @@ "0000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=3, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 3, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "000", @@ -8971,8 +12588,14 @@ "000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=4, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 4, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000", @@ -8990,8 +12613,14 @@ "0000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=8, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 8, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000", @@ -9001,8 +12630,14 @@ "0000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=10, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 10, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000", @@ -9011,8 +12646,14 @@ "0000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=11, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 11, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000", @@ -9020,26 +12661,50 @@ "000000000000000000000000000000000", "00000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=16, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 16, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000", "00000000000000000000000000000000", "000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=31, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 31, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(1024), .sparsity=32, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 1024 }, + .sparsity = 32, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=1, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 1, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0", @@ -9105,8 +12770,14 @@ "0000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=2, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 2, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00", @@ -9140,8 +12811,14 @@ "0000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=3, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 3, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "000", @@ -9165,8 +12842,14 @@ "000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=4, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 4, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000", @@ -9184,8 +12867,14 @@ "0000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=8, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 8, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000", @@ -9195,8 +12884,14 @@ "0000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=10, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 10, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000", @@ -9205,8 +12900,14 @@ "0000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=11, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 11, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000", @@ -9214,26 +12915,50 @@ "000000000000000000000000000000000", "00000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=16, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 16, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000", "00000000000000000000000000000000", "000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=31, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 31, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min=OPT_I64_C(INT64_MIN), .max=OPT_I64_C(4294967295), .sparsity=32, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = true, .value = INT64_MIN }, + .max = { .set = true, .value = 4294967295 }, + .sparsity = 32, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=1, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 1, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0", @@ -9299,8 +13024,14 @@ "0000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=2, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 2, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00", @@ -9334,8 +13065,14 @@ "0000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=3, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 3, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "000", @@ -9359,8 +13096,14 @@ "000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=4, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 4, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000", @@ -9378,8 +13121,14 @@ "0000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=8, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 8, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000", @@ -9389,8 +13138,14 @@ "0000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=10, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 10, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000", @@ -9399,8 +13154,14 @@ "0000000000000000000000000000000000000000", "00000000000000000000000000000000000000000000000000", "000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=11, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 11, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000", @@ -9408,22 +13169,41 @@ "000000000000000000000000000000000", "00000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=16, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 16, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000", "00000000000000000000000000000000", "000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=31, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 31, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000", "00000000000000000000000000000000000000000000000000000000000000", -}}, -{.value=INT64_MIN, .min={0}, .max={0}, .sparsity=32, { + }, +}, +{ + .value = INT64_MIN, + .min = { .set = false }, + .max = { .set = false }, + .sparsity = 32, + .expectEdges = { "root", "0000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", -}}, + }, +}, diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_decimal128.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_decimal128.cstruct index 20a9699..e10a7dd 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_decimal128.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_decimal128.cstruct @@ -1,4 +1,4 @@ -// This code is GENERATED! Do not edit! +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` // clang-format off { .lowerBound = mc_dec128_from_string("-100.000000"), diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_decimal128_precision.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_decimal128_precision.cstruct index 3d11b4c..b54308d 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_decimal128_precision.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_decimal128_precision.cstruct @@ -1,4 +1,4 @@ -// This code is GENERATED! Do not edit! +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` // clang-format off { .lowerBound = mc_dec128_from_string("0.000000"), diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_double.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_double.cstruct index 0e46f90..3976c60 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_double.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_double.cstruct @@ -1,4 +1,4 @@ -// This code is GENERATED! Do not edit! +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` // clang-format off { .lowerBound = -100.000000, diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_double_precision.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_double_precision.cstruct index f82e89d..961543c 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_double_precision.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_double_precision.cstruct @@ -1,4 +1,4 @@ -// This code is GENERATED! Do not edit! +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` // clang-format off { .lowerBound = 0.000000, @@ -299,7 +299,7 @@ .max = { .set = true, .value = 314.159265 }, .precision = { .set = true, .value = 6 }, .expectMincoverStrings = { - "0000010011100111000101111011", + "00000100111001110001011110111", "00000100111001110001011111", "000001001110011100011", "0000010011100111001", diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_int32.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_int32.cstruct index a8ab2ad..96e6a3c 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_int32.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_int32.cstruct @@ -1,4 +1,4 @@ -// This code is GENERATED! Do not edit! +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` // clang-format off { .lowerBound = -100, diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_int64.cstruct b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_int64.cstruct index 2b16928..e34a9f3 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_int64.cstruct +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-min-cover/mincover_int64.cstruct @@ -1,4 +1,4 @@ -// This code is GENERATED! Do not edit! +// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py` // clang-format off { .lowerBound = -100, diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/cmd.json new file mode 100644 index 0000000..b5d57a8 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/cmd.json @@ -0,0 +1,8 @@ +{ + "find": "test", + "filter": { + "encrypted": { + "$numberInt": "123456" + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-field-map.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-field-map.json new file mode 100644 index 0000000..e688460 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-field-map.json @@ -0,0 +1,19 @@ +{ + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-payload.json new file mode 100644 index 0000000..46b87e8 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/encrypted-payload.json @@ -0,0 +1,53 @@ +{ + "find": "test", + "filter": { + "$and": [ + { + "encrypted": { + "$gte": { + "$binary": { + "base64": "DQEBAAADcGF5bG9hZACZAAAABGcAhQAAAAMwAH0AAAAFZAAgAAAAABVoe9wkcCyHpbOGCU+k9auwnEcS2CtNpRqiecg98ONpBXMAIAAAAABvqHHsxgHdi12FXVttMVYYwNK4R2zYUjeXQHAURNBvzwVsACAAAAAAfmp4QWZF7LiYXH6RYjf1kc6OpgRnCadlHki6cRrMilsAABJjbQAIAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAASc3AAAgAAAAAAAAAQdGYABgAAABBtbgAAAACAEG14AP///38A", + "subType": "06" + } + } + } + }, + { + "encrypted": { + "$lte": { + "$binary": { + "base64": "DTsAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", + "subType": "06" + } + } + } + } + ] + }, + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ], + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc" + } + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/mongocryptd-reply.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/mongocryptd-reply.json new file mode 100644 index 0000000..ff9134f --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-find-int32/mongocryptd-reply.json @@ -0,0 +1,58 @@ +{ + "hasEncryptionPlaceholders": true, + "schemaRequiresEncryption": true, + "result": { + "find": "test", + "filter": { + "$and": [ + { + "encrypted": { + "$gte": { + "$binary": { + "base64": "AxABAAAQdAACAAAAEGEAAwAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAAQSNFZ4EjSYdhI0EjRWeJASA3YAsQAAAANlZGdlc0luZm8AawAAABBsb3dlckJvdW5kAEDiAQAIbGJJbmNsdWRlZAABEHVwcGVyQm91bmQAQOIBAAh1YkluY2x1ZGVkAAEQdHJpbUZhY3RvcgAGAAAAEGluZGV4TWluAAAAAIAQaW5kZXhNYXgA////fwAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAAEmNtAAgAAAAAAAAAEnMAAgAAAAAAAAAA", + "subType": "06" + } + } + } + }, + { + "encrypted": { + "$lte": { + "$binary": { + "base64": "A5oAAAAQdAACAAAAEGEAAwAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAAQSNFZ4EjSYdhI0EjRWeJASA3YAOwAAABBwYXlsb2FkSWQAAAAAABBmaXJzdE9wZXJhdG9yAAIAAAAQc2Vjb25kT3BlcmF0b3IABAAAAAASY20ACAAAAAAAAAAScwACAAAAAAAAAAA=", + "subType": "06" + } + } + } + } + ] + }, + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } + } + } + }, + "ok": { + "$numberDouble": "1.0" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/cmd.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/cmd.json new file mode 100644 index 0000000..ce0965f --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/cmd.json @@ -0,0 +1,11 @@ +{ + "insert": "test", + "documents": [ + { + "plainText": "sample", + "encrypted": { + "$numberInt": "123456" + } + } + ] +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-field-map.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-field-map.json new file mode 100644 index 0000000..e688460 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-field-map.json @@ -0,0 +1,19 @@ +{ + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-payload.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-payload.json new file mode 100644 index 0000000..934fe11 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-payload.json @@ -0,0 +1,40 @@ +{ + "insert": "test", + "documents": [ + { + "plainText": "sample", + "encrypted": { + "$binary": { + "base64": "C64LAAAFZAAgAAAAAFX/OCQuK7sgFC5OgvIzRF0iZF5yZhqqgVEw+BDk04D/BXMAIAAAAADf8ZGTnPqqur9tusELGqTbSNtoJgj8i071DXm7kQpcSgVwADEAAAAAAwECAwECAwECAwECAwECAz+VM8kdZjiqXJ2Kga/NSZuITHP/iMRHFXZ17XdXy4FMWwV1ABAAAAAEEjRWeBI0mHYSNBI0VniQEhB0ABAAAAAFdgBQAAAAABI0VngSNJh2EjQSNFZ4kBIBAgMBAgMBAgMBAgMBAgMB978eymjOG8LzTgudRZqpbK4Tm1RK3tB9QMB9lTWKiy6Wqp7twzRA/ZbjQ69RKj60BWUAIAAAAADrmnP3kS2GpCl+gdL2da90KHTkBX46iQ/sZRoj7uPz7AVsACAAAAAAlO36MaVLVRDFW6xrI+0UTkyQdFfSCEBPkZg8sFzuTJYSawAGAAAAAAAAAARnACcKAAADMAC2AAAABWQAIAAAAABx4c6MPMR3Yyxzi0dTMjQ7UdRNgI8uP2LTi1vhGYnLMAVzACAAAAAAon13gVyXE18K3ylqp/ovYStGulVBaekS2mKVRFq7RQgFbAAgAAAAAH5qeEFmRey4mFx+kWI39ZHOjqYEZwmnZR5IunEazIpbBXAAMQAAAAACAwECAwECAwECAwECAwECy273HayEz3hgoMYG56e0sxacPePKwPiqCCS575wlTLMxAAMxALYAAAAFZAAgAAAAALhKoC9+IzmWByMV7+lxHqBz30ckyd4wjXTJIaxvSHGQBXMAIAAAAADOFYCxSi5cl0dHBBpG2MuoCMK4VW7bnHkT4W0b8/S9QAVsACAAAAAA2ed4R4wYD6DT0P+N6o3gDJPE0DjljbRAv5vme3jb42sFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgMucSLry7LOh6S3NFriDyboyFWjjO7jUCKQmfnXNTVgRlsAAzIAtgAAAAVkACAAAAAA6d+xdtGaB4rPWNOM/dfLBsjgszgJ3nZIu6NMY7PGleMFcwAgAAAAAOoLJCMXdUXT5CP7ddF7NkbkHzTWmAJdEQnP3xG/VufdBWwAIAAAAADH9XHyaSTZUZNt8Z6XnKi7viLmxyO8TBuoRmwhAOkIogVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAViMN5HI9n2E2jIfq+NIBjTZq9V1WKXzuz6coSb44HleywADMwC2AAAABWQAIAAAAABHc/GW0GvNFnIAzns/1yI0xGl/Ir5cH5BLQckH+kV3fAVzACAAAAAAQmiJLIWjabGJeih4GboT6t/cn3SFOjMUgUpJrmQ8XUEFbAAgAAAAAOZbKzIqF/xRxwrHvwiWIdNZqj2l78DCYswNswCdUkc9BXAAMQAAAAACAwECAwECAwECAwECAwECK3sJsHWwtZbjBccUWeeIOOIGGMIOkyKsUwxlBaKiVPowAAM0ALYAAAAFZAAgAAAAAOW+ccgZnspe3Zk0B15sNoxYs+++vkIhLYDssUWrpf+ZBXMAIAAAAAC13nmuhE1cSoIdkJleu6iHCYZARpCxvagwSrdjvgaRUgVsACAAAAAAIrk7klUCamSAp05f9qK6PqR041yRVCaJ7dctpSUm5/gFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgNVutv0BdHOWmHtoNn6bEXHyRFbnxCJcfOzMiOveMdMVFsAAzUAtgAAAAVkACAAAAAAHDzIz2zmH3ABRBNEt4lMKBvbFr/Isvn120UyOZX2fO0FcwAgAAAAAC38Cjx6SPJmI+8cIdItT/DAqdCxJaLNeqYyxzGMte4GBWwAIAAAAAB2mov70YYtzeH4imEKJhjQUoXg3o3I54oyLFTZgru74QVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAZ97GY6ly8oxHf74/+Aef4L9HTES5QVj0JFhuQbLA3CFywADNgC2AAAABWQAIAAAAAD0ugfk8nq6aFeln4+QLIhFyOkLafGcozN8MvybVLzaRgVzACAAAAAAC1ORUt0477aATkfBAN86Ky6TzUN4zYnGFdZw5VLJ3hcFbAAgAAAAAAs9x1SnVpMfNv5Bm1aXGwHmbbI9keWa9HRD35XuCBK5BXAAMQAAAAACAwECAwECAwECAwECAwECYkARzi0rM5HqMaitQIKh+RNJSvXzZJh+x5BcTpRX16wwAAM3ALYAAAAFZAAgAAAAANCNn0wJp9IH48jKhaXrMNEZxL+8bFLBDK4cdcRKisXwBXMAIAAAAAAwYLl1BiMdwdX0D4kOg6Ny/vAShkyLLpYLOj//l8nv8QVsACAAAAAADxH2z9GufFM6RT5+pgWycCbSSY0peGvRXeT/U6u25NEFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgPQBBsvh7+P0TYEP8mqVE4yPmcJX8yz4s2IQqszUQgy91sAAzgAtgAAAAVkACAAAAAApUDgJrXbR7rYptc8rNKDAMTJJgpWx3wJ5Ei6ExI4cKsFcwAgAAAAAFYLdRWwhup6c51dwxz7JtWZ9hiWTI45RNME1HAiNLTlBWwAIAAAAAAK6ZFHvQOghjlhXsLbZmhDLlW+nCV3NrZD9Ue7y3/0ngVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAeSMZqdvBdItTYy5HS7IFqekQvk1jCmX7uRXqkdlgipmywADOQC2AAAABWQAIAAAAACnNRIgrtUTrL9bvDzNfdzpGsdqBElHVWVpYyPXwSwrvgVzACAAAAAAjmBoFQHWGwST1BE0yaBiekIcYVsoUf/BSrLwO9UhtEsFbAAgAAAAAEe9aNvZUOhoa4IYjG0TUFY0Lbx6KYY//F0HqCDbN/u7BXAAMQAAAAACAwECAwECAwECAwECAwEC53PoifHFxyP5q/5Yif35qH/G5u2j+O55mPTckBO/vfAwAAMxMAC2AAAABWQAIAAAAADO9uLhaBzFY2pp5k2huL0y7Ia9bbX9Td+8jbnze8vEoAVzACAAAAAAqE4YrbpDF0KstI1C6t+5gafrNKpWWc0gzHNa1VbxPjgFbAAgAAAAABkNIn+3njU/Zxu3Jz1yp3hxtx8KveIfzSQx6uLAsQLYBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDSCq69zvfhVJPRL0CTghUwWd8L3PWYQF7TwvOGZAw4z5bAAMxMQC2AAAABWQAIAAAAABugPtcm/HV5MD8yyuw4bpcdO1+K8CkSbE/dhzK93fyJAVzACAAAAAAuKJP+IQVI2kYA02OeeHFQEmvuVVPFYtpD7nAcl4U8rYFbAAgAAAAAJRkWtjoKRlC5wNyXtyBUyPeH8hFa0fcZTw8R8alLt7QBXAAMQAAAAABAgMBAgMBAgMBAgMBAgMBCiVcSluWGz4mEqlQS9L1MnQbWPaPsiXDOOq+RRmibDXLAAMxMgC2AAAABWQAIAAAAAC6uNqCo6p+ohuqlioUo7bhj6L+0kJpFl3yLYfYhqbnrAVzACAAAAAAH6WDk481/wTTL/Y6t765GCYPH0niPXWzamTeZ6lEQkcFbAAgAAAAABhXLMOXrnco598ejjUHAkNGZR8eNVnDMWrAuQ16j2O/BXAAMQAAAAACAwECAwECAwECAwECAwECdrYDD38mIyO5UBlW9+MiyhvVmP9plGQLuCLyzG/aS/wwAAMxMwC2AAAABWQAIAAAAABn8GOJ0BUhqxsCMujadpEuMjQH/JqjdSe+d7ck4BJpBgVzACAAAAAA/+5+gxu0s/JHvMroY0hgg4/pNDl6+FbjkVVL4pp0wKAFbAAgAAAAAIZjTmkgXeFszdl7b+WoFTth6LSUyRYvg6eh5JiOaoBYBXAAMQAAAAADAQIDAQIDAQIDAQIDAQIDH4rc2ZooIeKkTPqox5+Nw09+L+D6wJq4Ei3fLly1HaZbAAASc3AAAgAAAAAAAAAQdGYABgAAABBtbgAAAACAEG14AP///38A", + "subType": "06" + } + } + } + ], + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ], + "escCollection": "enxcol_.test.esc", + "ecocCollection": "enxcol_.test.ecoc" + } + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/mongocryptd-reply.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/mongocryptd-reply.json new file mode 100644 index 0000000..2ad49ec --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/auto-insert-int32/mongocryptd-reply.json @@ -0,0 +1,45 @@ +{ + "hasEncryptionPlaceholders": true, + "schemaRequiresEncryption": true, + "result": { + "insert": "test", + "encryptionInformation": { + "type": { + "$numberInt": "1" + }, + "schema": { + "db.test": { + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encrypted", + "bsonType": "int", + "queries": { + "queryType": "range" + } + } + ] + } + } + }, + "documents": [ + { + "plainText": "sample", + "encrypted": { + "$binary": { + "base64": "A30AAAAQdAABAAAAEGEAAwAAAAVraQAQAAAABBI0VngSNJh2EjQSNFZ4kBIFa3UAEAAAAAQSNFZ4EjSYdhI0EjRWeJASA3YAHgAAABB2AEDiAQAQbWluAAAAAIAQbWF4AP///38AEmNtAAgAAAAAAAAAEnMAAgAAAAAAAAAA", + "subType": "06" + } + } + } + ] + }, + "ok": { + "$numberDouble": "1.0" + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/expected.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/expected.json new file mode 100644 index 0000000..192fb91 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/expected.json @@ -0,0 +1,26 @@ +{ + "v": { + "$and": [ + { + "age": { + "$gte": { + "$binary": { + "base64": "DYECAAADcGF5bG9hZAAZAgAABGcABQIAAAMwAH0AAAAFZAAgAAAAANBGT3k4GTmoze5hCRukb6u82SvYtFyGp+AHjlySsjWOBXMAIAAAAAB9cQ+iwhaAuhOnOn/BFalNNBn3Tx1mHngGdjzKvNPfsgVsACAAAAAA5ZNdJZh+4XZcHqJMhqWcLUo4YkxCxPhhRU7UFru8pk8AAzEAfQAAAAVkACAAAAAAzrlE+7ZYgnH71G+SpzjCefAEj4qNkUQOfn0FUFuKWycFcwAgAAAAAKZDfaea7ZYGynYzTtP38WQAewOs6QD3NH4RO9XwuJG5BWwAIAAAAACpq6FrRDHryiZeM1B50z/fz/J5yK3fEqAlFj4E6KCdSwADMgB9AAAABWQAIAAAAABTX/+x7fmCvi5gAWgsy5xZowLqeEc/z1qE7Eh9QkpMmQVzACAAAAAAjOLpo8K1z0hnG5U/e+p5IVCfR23vd98ZDgqy00xqJuwFbAAgAAAAAFqIYZydW8nwOUai0Cbz6IKBHpkuCbTP/VsBNDG9j1wUAAMzAH0AAAAFZAAgAAAAADgmrmBDpEvWF++05l1otn4vG6Q+GoYpGgdV2EIGSYXaBXMAIAAAAAD2b6bl3/wn2zPllR9z8Kl96rDn8OwdHZuVhUC9sYjFngVsACAAAAAARtUrQP0hYeNlaA1/I+sENuShjFgWyxY3Jw9URdcLiJAAABJjbQABAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAASc3AAAgAAAAAAAAAQdGYABgAAABBtbgAAAAAAEG14AIfWEgAA", + "subType": "06" + } + } + } + }, + { + "age": { + "$lte": { + "$binary": { + "base64": "DTsAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", + "subType": "06" + } + } + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/to-encrypt.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/to-encrypt.json new file mode 100644 index 0000000..4c294e8 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32-defaults/to-encrypt.json @@ -0,0 +1,20 @@ +{ + "v": { + "$and": [ + { + "age": { + "$gte": { + "$numberInt": "23" + } + } + }, + { + "age": { + "$lte": { + "$numberInt": "35" + } + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32/expected.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32/expected.json new file mode 100644 index 0000000..472240e --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32/expected.json @@ -0,0 +1,26 @@ +{ + "v": { + "$and": [ + { + "age": { + "$gte": { + "$binary": { + "base64": "DYEDAAADcGF5bG9hZAAZAwAABGcABQMAAAMwAH0AAAAFZAAgAAAAANBGT3k4GTmoze5hCRukb6u82SvYtFyGp+AHjlySsjWOBXMAIAAAAAB9cQ+iwhaAuhOnOn/BFalNNBn3Tx1mHngGdjzKvNPfsgVsACAAAAAA5ZNdJZh+4XZcHqJMhqWcLUo4YkxCxPhhRU7UFru8pk8AAzEAfQAAAAVkACAAAAAAzrlE+7ZYgnH71G+SpzjCefAEj4qNkUQOfn0FUFuKWycFcwAgAAAAAKZDfaea7ZYGynYzTtP38WQAewOs6QD3NH4RO9XwuJG5BWwAIAAAAACpq6FrRDHryiZeM1B50z/fz/J5yK3fEqAlFj4E6KCdSwADMgB9AAAABWQAIAAAAAA9l5+QldlpI2N4eSiV+2l4tS9xZM+Y8kwcP+KhiEA8owVzACAAAAAAmdQflu77krN/4fFaB4la/ZWystLLh6nNv6xE9ErNZmMFbAAgAAAAACJbpdQ2++FVjMz+SdScn4lx3wsi1Y9gBcJozBfHuC6dAAMzAH0AAAAFZAAgAAAAAAhh9K4YcA+N8ACgj7B4smCyJmmJImd5oOUxjgM3T208BXMAIAAAAAB8LMl/6O3elk8pcE6o/WWd6HQKpQgr22l1tt2CpA+V7QVsACAAAAAAIMPlQ/IXn7oI3v3ltx2/1ql4oP/HRQPRjFyh/qTXANoAAzQAfQAAAAVkACAAAAAAXvLR5mSdJiSJ1DFwqIs6GYKvY+1bd0llpUdegS3y6tEFcwAgAAAAABAbG+tZXZ/z9VokQYAH23Kd7R4B9hjN0M3kWn/KBj8CBWwAIAAAAAACdaE9Ls6mFpsHzPBdVxPze4wHSHyPOW9xjCKEW3nYKgADNQB9AAAABWQAIAAAAAALlsQ6TaYfVYomaBlpbXtQcSyRgpJWDQVMh9YGaoJKwwVzACAAAAAA2OMU7sh4xR5O2482Idkiluu2zVJ2/OytctuyOxrgBWsFbAAgAAAAAA8vwTEAaqZNyh/H/6rELrEWzB/Q+JsF/NJ3zszdMjy+AAASY20AAQAAAAAAAAAAEHBheWxvYWRJZAAAAAAAEGZpcnN0T3BlcmF0b3IAAgAAABBzZWNvbmRPcGVyYXRvcgAEAAAAEnNwAAMAAAAAAAAAEHRmAAQAAAAQbW4AAAAAABBteACH1hIAAA==", + "subType": "06" + } + } + } + }, + { + "age": { + "$lte": { + "$binary": { + "base64": "DTsAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgACAAAAEHNlY29uZE9wZXJhdG9yAAQAAAAA", + "subType": "06" + } + } + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32/to-encrypt.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32/to-encrypt.json new file mode 100644 index 0000000..4c294e8 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-find-int32/to-encrypt.json @@ -0,0 +1,20 @@ +{ + "v": { + "$and": [ + { + "age": { + "$gte": { + "$numberInt": "23" + } + } + }, + { + "age": { + "$lte": { + "$numberInt": "35" + } + } + } + ] + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-insert-double/expected.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-insert-double/expected.json new file mode 100644 index 0000000..b518db1 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-insert-double/expected.json @@ -0,0 +1,8 @@ +{ + "v": { + "$binary": { + "base64": "C2QHAAAFZAAgAAAAALhaV7AbX3sF2A4xhA3wIdk4qL/eFe7aZpAa1DnM2kSTBXMAIAAAAACOMuCmd823x6f7jsONJvKeL8wOiR68hhvu0dlvYoxS4QVwADEAAAAAAwECAwECAwECAwECAwECA25WQvz2USXXRAu+gynxH97vWxVQnoRKQG2pTaOkTY/nWwV1ABAAAAAEEjRWeBI0mHYSNBI0VniQEhB0AAEAAAAFdgBQAAAAABI0VngSNJh2EjQSNFZ4kBIBAgMBAgMBAgMBAgMBAgMBwLKhtxuduoYSToLyr19j8+j+DHvJPS3XBVIHUMBjyS23HbcAYCgSw2kR1oBL6wTbBWUAIAAAAADrmnP3kS2GpCl+gdL2da90KHTkBX46iQ/sZRoj7uPz7AVsACAAAAAAiWNW98E+po41ct7A9qFXR6tOJ+C+TiNsYjrf6YBFdfoSawABAAAAAAAAAARnAM0FAAADMAC2AAAABWQAIAAAAAAQ4DndUIxNVcQbeCUb4fjmceM6kT/THUMUu7yx/7fbRQVzACAAAAAAtol+lj6hLJuanENCnlMN6Rmgp04cveQw9LviWaTz8sgFbAAgAAAAAAB5IMUmXk1/yctyMDORpFDfUeqesGwHjXgfKfd67hMUBXAAMQAAAAACAwECAwECAwECAwECAwEC35r+Cs6y8Lzw46wu3g6WOyR6IPiXFPWIJv3O8mJt+3MxAAMxALYAAAAFZAAgAAAAAFK5izd0ZDT135CYAGOt9lk4ifpTzhBe/8CumApPOXNkBXMAIAAAAACxQUZGVGEmG3BUwnAfRO5Mhttn1Tst3JMCZCR8JjXr3AVsACAAAAAAA4hleX/0UT5MKUq2TBhzQUmq5sMqlfkmFyO90Fvz5p8FcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgNRJeQc1f20C5Ok8jC7kwMMRkx8DLsVEMiBHLCw4PQ22lsAAzIAtgAAAAVkACAAAAAA7+qR6azxFnahvjFVFRZ5DtLNKgJfX0XOGCrReRAqWz4FcwAgAAAAACMYa0yh6yIIe5ZGxBOrCymO5XJU0mL5WY+Ra0cCZYPgBWwAIAAAAACDq4A9lSlrKYJqyoMst0vEkbTVzmG2MZOMOwVM9apfoAVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAZGfeP5+aBpfRYeiGiGYO1uzUZP3EsVX87jCFXBF0x1jywADMwC2AAAABWQAIAAAAAAkX6RCK3jBegSxwLBf5UXNvgDJVAueuSdKEhIvmPOS1QVzACAAAAAA8nErlZj5TxlcSxhyTglmvilPVSOdj4Fte4Ch3h8wBB4FbAAgAAAAAMiSVZlV86lAL4NPTAsp7+2y1GuICLjXV0vdY0/abTH7BXAAMQAAAAACAwECAwECAwECAwECAwECm2KrCWjqkz42NPceDlT9bBSV0pUWJpDVqcaNddmuDaUwAAM0ALYAAAAFZAAgAAAAAGZmOclRRXANFpclF+VP8e/onm/zQPS7QkoE3ptUtZRCBXMAIAAAAAALaMsYYNTs3MprY7WRchKAIdGDULAHlJbFjHlMJfxbtAVsACAAAAAAuLSbGn8yWQatCfxFq63aSG81xhL4VdNrq1S61AbihSMFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgPrDGlC4Uh+zCmbU/U1pf/A4UaYiTA/WM1G9O2A4z2GslsAAzUAtgAAAAVkACAAAAAAjbLuXNZXd0/yom0v+4ESfI8HOVcgQD3wCp6GBsMt6lQFcwAgAAAAAC58vjDehb7mDU0jUjS1qmyOB4jwx5Pq39dO5shO+rysBWwAIAAAAAA3YMxxqO2vRJlAMcjML86nucUGcnrd9npxzz7wrExzgwVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAZz7rYIBBoaxM1zHjAaGmh6zs2lTBzREdeAdmP8JTCIvywADNgC2AAAABWQAIAAAAABb2oc8Q6Q0skHDGDDtjx7bCZq0bUIi+ltESICucx0UCAVzACAAAAAAHh2HU8T2s/Tb+7MUMnpLjvFE/h1TUF/CdIIPjnOiKXIFbAAgAAAAAIszvCwG/imDGHPdZzXeiNqRYv4GRV8G5rvQYXWUkJRcBXAAMQAAAAACAwECAwECAwECAwECAwECdw4HzzTlb9OxhFx4cifQXMyeeavY+U56psQjJbU8IMkwAAM3ALYAAAAFZAAgAAAAABzHcTf5Q7tCDmM2iWj5hn8YE6CgYG5UbdZZZB74+42vBXMAIAAAAAAJKy5sUK1se93nLyJCo9D/vd2zwv5fbKeMI4B6RW047QVsACAAAAAA+KkgAsZn/tg1wsxNM0JTQouYEf9NDVjSBzbP+MkddVAFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgPpT4w20TH+az4XH2LmdD2/fUqoG35noPwPWxS2g6zl61sAABJzcAADAAAAAAAAABBwbgACAAAAEHRmAAQAAAABbW4AAAAAAAAAAAABbXgAAAAAAIfWMkEA", + "subType": "06" + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-insert-int32-defaults/expected.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-insert-int32-defaults/expected.json new file mode 100644 index 0000000..42c2b5d --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-insert-int32-defaults/expected.json @@ -0,0 +1,8 @@ +{ + "v": { + "$binary": { + "base64": "Cw0IAAAFZAAgAAAAALzbu+LfseFckQJg1Ylo/9nBhe7hxjFLXcZoirJJ4PlxBXMAIAAAAACOQJsWGHdNI2AXICcsv3q3rYFe0S/kvPGbUBQmmn5naQVwADEAAAAAAwECAwECAwECAwECAwECA24kOUyZ698zg+cQZ4hol/dtFkUIr9xwqhgogOpcv7pvWwV1ABAAAAAEEjRWeBI0mHYSNBI0VniQEhB0ABAAAAAFdgBQAAAAABI0VngSNJh2EjQSNFZ4kBIBAgMBAgMBAgMBAgMBAgMB978eymjOG8LzTgudRZqpbK4Tm1RK3tB9QMB9lTWKiy6Wqp7twzRA/ZbjQ69RKj60BWUAIAAAAADrmnP3kS2GpCl+gdL2da90KHTkBX46iQ/sZRoj7uPz7AVsACAAAAAAlO36MaVLVRDFW6xrI+0UTkyQdFfSCEBPkZg8sFzuTJYSawABAAAAAAAAAARnAIYGAAADMAC2AAAABWQAIAAAAADDDSwgzG3b3hAnx/QM/8RGNV7qvbq+fAFpPF7RSN6W/AVzACAAAAAAjW2YlJV8aul4reu19mYd5nynwgS5giAc6AW7rTsXfEkFbAAgAAAAAA6eOZwxxhUyuExW2kjHcKJmNCrEPFQ9vS9YbrzP67TgBXAAMQAAAAACAwECAwECAwECAwECAwEC5H4YCGVvts4S0gTZtjuGNEF9RbIyKzGkOkOXBv2JdfIxAAMxALYAAAAFZAAgAAAAAEMbeAokq9+EI0VAu9kzSqGXKkgWTt7fcnJgp40qUzxhBXMAIAAAAADWfY3LqVm2iPeXvaZrJnHCNTSo7wfb7xEkPY8YN4MdEQVsACAAAAAAl7RsOFQfWxmV2cMZafTExrUJC43pyC/+L/peqek9Lf0FcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgM2GS+RKMUkmBRnjebP8ZyC9aOzNofjI0qnRRvU8ULAF1sAAzIAtgAAAAVkACAAAAAAkJnPJd1pQ1WTaAnx7PevE42PCOA3+5GLN+PLOr84qYYFcwAgAAAAANfCPZjI5EvdhScmqaqtEf2Brjlo1gVe/xMEOPWfdB87BWwAIAAAAAA5zR9OnG49Xrn3grU7zBDon+oj+/1FUIOptLvwesWUvQVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAWVFLioXZ3OKuzbCd5ieIY+8GtjLFqLwVSRXRsLYwoG4ywADMwC2AAAABWQAIAAAAAD+Ea3yOx7sqUO7kUA8MvDlp0KbcR9S0CZn6yQqmZFRLwVzACAAAAAAIxyzUPpOb4HsMQRnbN3FH9sqGIjHsmKEdA0jTBCIjokFbAAgAAAAAIFEk9LC+wpdnt+iy3OTuzvc/W/4y7GWyhLN8YIFWpBZBXAAMQAAAAACAwECAwECAwECAwECAwECSg8zzApds6aGTusLLIBezebwnz5MG3M8pksP59YWhzIwAAM0ALYAAAAFZAAgAAAAAG8oo7+6uTa9nxjpXDpMofmlbRMxKSIGXsYgL5OGRE3ABXMAIAAAAAC81iL904byU1ACGkbBkxemVDQkxAyvPH+YBFmeYu5XCAVsACAAAAAABcm2+tbs0VSGFn9rDvWyvhuIRVDepRdoIvNa6TRv3zkFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgNcsoCnUhpgQ7PyKgZlRPrmlKM/HYyX8CQbfM1SpC+KDlsAAzUAtgAAAAVkACAAAAAAN1yutwxk1no+d0K7uwq121gaj6/APpV81NvMBSbh9QsFcwAgAAAAADotY5M6YW1+5/baxwt+IdliMsVZwd5Igr0coiqGiXNFBWwAIAAAAACLCFou5eC94e2pRXNjJ8oPkENRCDGdw9eZP7Kvgb2mCAVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAYiqcCHl4lUp2ec+GTlNEatfhiT6AXnmKIpP3B3BP+3GywADNgC2AAAABWQAIAAAAACxK8LFOEPUtM0uhqsrNd2VxlEAAboEfCcme14stervuwVzACAAAAAAF83o3sy5t9k6FW0br92D/gK0GtnqWYcTLkKDCZJJ/RwFbAAgAAAAAI+sI8AzBUAhDs2DSTh7StO5rgbgse0idO29VwOikD69BXAAMQAAAAACAwECAwECAwECAwECAwECft5oQjyqa/5QaoJ374AYLD9unW9h8Jar/ASvolTX9KcwAAM3ALYAAAAFZAAgAAAAACERygJgbMzz/kAGWZ7VGvByGUqPK9Ofs8jhN5zaldOFBXMAIAAAAACbP0SY0GDEKmYqCYatldSkTuzCS2xMCAJzfeRzqWyTswVsACAAAAAAx3b30GiSDqGKGibsVkC0wPEtLdUn5oieC/mR0h0PfooFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgN7W+bCUfxWOoXaOcYJQjnkjnvZkux0xFnwBXC/b61OtVsAAzgAtgAAAAVkACAAAAAAfuQBgBMx9gTdzh8VtYmaXdOUzVw8eIzZEk36kyGQZ8YFcwAgAAAAAOQaG1G8sbv0RuwezsEIxWfAXhOwpNnWxPrOueCWX9z5BWwAIAAAAACEBB9msU96lZNyT2Ory8KBNcfwHUZew4nuAMFzpU0kTwVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAVadCONjMoOjeP36EPM79RX96vITZH54bs2dx9fR6UJ6ywAAEnNwAAIAAAAAAAAAEHRmAAYAAAAQbW4AAAAAABBteACH1hIAAA==", + "subType": "06" + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json new file mode 100644 index 0000000..07cc650 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json @@ -0,0 +1,8 @@ +{ + "v": { + "$binary": { + "base64": "C+IFAAAFZAAgAAAAALzbu+LfseFckQJg1Ylo/9nBhe7hxjFLXcZoirJJ4PlxBXMAIAAAAACOQJsWGHdNI2AXICcsv3q3rYFe0S/kvPGbUBQmmn5naQVwADEAAAAAAwECAwECAwECAwECAwECA24kOUyZ698zg+cQZ4hol/dtFkUIr9xwqhgogOpcv7pvWwV1ABAAAAAEEjRWeBI0mHYSNBI0VniQEhB0ABAAAAAFdgBQAAAAABI0VngSNJh2EjQSNFZ4kBIBAgMBAgMBAgMBAgMBAgMB978eymjOG8LzTgudRZqpbK4Tm1RK3tB9QMB9lTWKiy6Wqp7twzRA/ZbjQ69RKj60BWUAIAAAAADrmnP3kS2GpCl+gdL2da90KHTkBX46iQ/sZRoj7uPz7AVsACAAAAAAlO36MaVLVRDFW6xrI+0UTkyQdFfSCEBPkZg8sFzuTJYSawABAAAAAAAAAARnAFsEAAADMAC2AAAABWQAIAAAAADDDSwgzG3b3hAnx/QM/8RGNV7qvbq+fAFpPF7RSN6W/AVzACAAAAAAjW2YlJV8aul4reu19mYd5nynwgS5giAc6AW7rTsXfEkFbAAgAAAAAA6eOZwxxhUyuExW2kjHcKJmNCrEPFQ9vS9YbrzP67TgBXAAMQAAAAACAwECAwECAwECAwECAwEC5H4YCGVvts4S0gTZtjuGNEF9RbIyKzGkOkOXBv2JdfIxAAMxALYAAAAFZAAgAAAAAEMbeAokq9+EI0VAu9kzSqGXKkgWTt7fcnJgp40qUzxhBXMAIAAAAADWfY3LqVm2iPeXvaZrJnHCNTSo7wfb7xEkPY8YN4MdEQVsACAAAAAAl7RsOFQfWxmV2cMZafTExrUJC43pyC/+L/peqek9Lf0FcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgM2GS+RKMUkmBRnjebP8ZyC9aOzNofjI0qnRRvU8ULAF1sAAzIAtgAAAAVkACAAAAAASubnYKt2+pegwuJwp7dxPEyRP9GvmJgFinGHU0f9CpIFcwAgAAAAAB/mpuAOeTGXLOVFgdx0eXJL51Zh2D5L2vZxwAgghlI+BWwAIAAAAAAQL6NCvBkhQ9ulCrwaNULOgv7Uhfp3ZhsiTHSOF5GySgVwADEAAAAAAQIDAQIDAQIDAQIDAQIDAa1htVLR+gnAEvShX+5HSQB2U7fCGJnlcMEivj9nMMy9ywADMwC2AAAABWQAIAAAAABvKKO/urk2vZ8Y6Vw6TKH5pW0TMSkiBl7GIC+ThkRNwAVzACAAAAAAvNYi/dOG8lNQAhpGwZMXplQ0JMQMrzx/mARZnmLuVwgFbAAgAAAAAAXJtvrW7NFUhhZ/aw71sr4biEVQ3qUXaCLzWuk0b985BXAAMQAAAAACAwECAwECAwECAwECAwEC1cWiYSOVLnQ6ffUqgc6MdGnuo3KHBi3HSkJ1NaRwXrMwAAM0ALYAAAAFZAAgAAAAAIMIjVhHf3tXJuPJ8mfbyeyXEutLfChd4KW3CK5y8gVqBXMAIAAAAABqPndgeb1Hei5AUcmBUdeO2gyoqqfq/2mf2oQEYClk3wVsACAAAAAAmeoE0x+Ci2vQGzzdW6c6SVIMBWeg7wUACzaaNQt+g/YFcAAxAAAAAAMBAgMBAgMBAgMBAgMBAgOKWtU6+CHVas2wYYklhjrOGpuzcyfSMzIcohDIpui52VsAAzUAtgAAAAVkACAAAAAAIRHKAmBszPP+QAZZntUa8HIZSo8r05+zyOE3nNqV04UFcwAgAAAAAJs/RJjQYMQqZioJhq2V1KRO7MJLbEwIAnN95HOpbJOzBWwAIAAAAADHdvfQaJIOoYoaJuxWQLTA8S0t1SfmiJ4L+ZHSHQ9+igVwADEAAAAAAQIDAQIDAQIDAQIDAQIDASm4VyoP4/x9WDvtWJ+m5NZzWCPorOumqEQumkTu2g0wywAAEnNwAAMAAAAAAAAAEHRmAAQAAAAQbW4AAAAAABBteACH1hIAAA==", + "subType": "06" + } + } +} diff --git a/ext/libmongocrypt/libmongocrypt/test/data/tokens/README.md b/ext/libmongocrypt/libmongocrypt/test/data/tokens/README.md index d062cc7..8e595db 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/tokens/README.md +++ b/ext/libmongocrypt/libmongocrypt/test/data/tokens/README.md @@ -7,7 +7,7 @@ Each document is a single-depth set of key value pairs. All values are 32 octet | ----- | ----------- | | root | The base key from which all other tokens are derived. | | value | Data used in `DerivedFromData` tokens. | -| counter | Data used in `DerivedFromDataAndCounter` tokens. | +| contentionFactor | Data used in `DerivedFromDataAndContentionFactor` tokens. | | collectionsLevel1Token | HMAC(root, 1) | | serverTokenDerivationLevel1Token | HMAC(root, 2) | | serverDataEncryptionLevel1Token | HMAC(root, 3) | @@ -18,9 +18,12 @@ Each document is a single-depth set of key value pairs. All values are 32 octet | EDCDerivedFromDataToken | HMAC(EDCToken, value) | | ESCDerivedFromDataToken | HMAC(ESCToken, value) | | ECCDerivedFromDataToken | HMAC(ECCToken, value) | -| EDCDerivedFromDataTokenAndCounter| HMAC(EDCDerivedFromDataToken, counter) | -| ESCDerivedFromDataTokenAndCounter| HMAC(ESCDerivedFromDataToken, counter) | -| ECCDerivedFromDataTokenAndCounter| HMAC(ECCDerivedFromDataToken, counter) | +| EDCDerivedFromDataTokenAndContentionFactor| HMAC(EDCDerivedFromDataToken, contentionFactor) | +| ESCDerivedFromDataTokenAndContentionFactor| HMAC(ESCDerivedFromDataToken, contentionFactor) | +| ECCDerivedFromDataTokenAndContentionFactor| HMAC(ECCDerivedFromDataToken, contentionFactor) | +| EDCTwiceDerivedToken | HMAC(EDCDerivedFromDataTokenAndContentionFactor, 1) | +| ESCTwiceDerivedTagToken | HMAC(ESCDerivedFromDataTokenAndContentionFactor, 1) | +| ESCTwiceDerivedValueToken | HMAC(ESCDerivedFromDataTokenAndContentionFactor, 2) | | serverDerivedFromDataToken | HMAC(serverTokenDerivationLevel1Token, value) | | serverCountAndContentionFactorEncryptionToken | HMAC(serverDerivedFromDataToken, 1) | | serverZerosEncryptionToken | HMAC(serverDerivedFromDataToken, 2) | diff --git a/ext/libmongocrypt/libmongocrypt/test/data/tokens/mc.json b/ext/libmongocrypt/libmongocrypt/test/data/tokens/mc.json index 5d05d06..cb419a6 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/tokens/mc.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/tokens/mc.json @@ -1,7 +1,7 @@ { "root": "6eda88c8496ec990f5d5518dd2ad6f3d9c33b6055904b120f12de82911fbd933", "value": "c07c0df51257948e1a0fc70dd4568e3af99b23b3434c9858237ca7db62db9766", - "counter": 1234567890, + "contentionFactor": 1234567890, "collectionsLevel1Token": "ff2103ff205a36f39704f643c270c129919f008c391d9589a6d2c86a7429d0d3", "serverDataEncryptionLevel1Token": "d915ccc1eb81687fb5fc5b799f48c99fbe17e7a011a46a48901b9ae3d790656b", "serverTokenDerivationLevel1Token": "1adc114b462741e6ac9f52eacf3dcb8cbca19827693c571d9418fda570c29d82", @@ -13,9 +13,13 @@ "ESCDerivedFromDataToken": "acb3fab332131bbeaf112814f29ae0f2b10e97dc94b62db56c594661248e7467", "ECCDerivedFromDataToken": "826cfd35c35dcc7d4fbe13f33a3520749853bd1ea4c47919482252fba3a70cec", "serverDerivedFromDataToken": "4a671dbf25d68b6c040a077dabb4e63869e03f4d466803609233b16356ec6d66", - "EDCDerivedFromDataTokenAndCounter": "70fb9a3f760996f2f1438c5bf2a4d52bcba01b0badc3596276f49ffb2f0b136e", - "ESCDerivedFromDataTokenAndCounter": "7076c7b05fb4be4fe585eed930b852a6d088a0c55f3c96b50069e8a26ebfb347", - "ECCDerivedFromDataTokenAndCounter": "6c6a349956c19f9c5e638e612011a71fbb71921edb540310c17cd0208b7f548b", + "EDCDerivedFromDataTokenAndContentionFactor": "70fb9a3f760996f2f1438c5bf2a4d52bcba01b0badc3596276f49ffb2f0b136e", + "ESCDerivedFromDataTokenAndContentionFactor": "7076c7b05fb4be4fe585eed930b852a6d088a0c55f3c96b50069e8a26ebfb347", + "ECCDerivedFromDataTokenAndContentionFactor": "6c6a349956c19f9c5e638e612011a71fbb71921edb540310c17cd0208b7f548b", + "EDCTwiceDerivedToken": "3643fd370e2719c03234cdeec787dfdc7d8fceecafa8a992e3c1f9d4d53449fe", + "ESCTwiceDerivedTagToken": "c73bc4ff5e70222c653140b2b4998b4d62db973f20f116f66ff811a9a907a78f", + "ESCTwiceDerivedValueToken": "34150c6f5ab56dc39ddb935accb7f53e5276322fa937650b76a4dda9723d6fba", "serverCountAndContentionFactorEncryptionToken": "a8c4a477e5518a527f718a5a1530919f2dad13b1f3559833e17b479711cbdbb9", - "serverZerosEncryptionToken": "95fda1e139ef1dc84260d4d3ebaab7627a9676f4af7aeb1b596c7c14a0b3a2ea" + "serverZerosEncryptionToken": "95fda1e139ef1dc84260d4d3ebaab7627a9676f4af7aeb1b596c7c14a0b3a2ea", + "AnchorPaddingTokenRoot": "d5072cc56d9241470b9771292c3f75d950cba1cf842ca6707d1adfec5ec6f3e7" } \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/data/tokens/server.json b/ext/libmongocrypt/libmongocrypt/test/data/tokens/server.json index f98d8b0..62127a2 100644 --- a/ext/libmongocrypt/libmongocrypt/test/data/tokens/server.json +++ b/ext/libmongocrypt/libmongocrypt/test/data/tokens/server.json @@ -1,7 +1,7 @@ { "root": "e3d9219f79586582112740b2add88e1030d91926ae8afc13ee575cfb8bb965b7", "value": "c07c0df51257948e1a0fc70dd4568e3af99b23b3434c9858237ca7db62db9766", - "counter": 1234567890, + "contentionFactor": 1234567890, "collectionsLevel1Token": "BD53ACAC665EDD01E0CA30CB648B2B8F4967544047FD4E7D12B1A9BF07339928", "serverTokenDerivationLevel1Token": "C17FDF249DE234F9AB15CD95137EA7EC82AE4E5B51F6BFB0FC1B8FEB6800F74C", "serverDataEncryptionLevel1Token": "EB9A73F7912D86A4297E81D2F675AF742874E4057E3A890FEC651A23EEE3F3EC", @@ -13,9 +13,13 @@ "ESCDerivedFromDataToken": "DE6A1AC292BC62094C33E94647B044B9B10514317B75F4128DDA2E0FB686704F", "ECCDerivedFromDataToken": "9A95D4F44734447E3F0266D1629513A0B7698CCE8C1524F329CE7970627FFD06", "serverDerivedFromDataToken": "EDBC92F3BFE4CCB3F088FED8D42379A83F26DC37F2B6D513D4F568A6F32C8C80", - "EDCDerivedFromDataTokenAndCounter": "D8CC38AE6A64BD1BF195A2D35734C13AF2B1729AD1052A81BE00BF29C67A696E", - "ESCDerivedFromDataTokenAndCounter": "8AAF04CBA6DC16BFB37CADBA43DCA66C183634CB3DA278DE174556AE6E17CEBB", - "ECCDerivedFromDataTokenAndCounter": "E9580F805E0D07AF384EBA185384F28A49C3DB93AFA4A187A1F4DA129271D82C", + "EDCDerivedFromDataTokenAndContentionFactor": "D8CC38AE6A64BD1BF195A2D35734C13AF2B1729AD1052A81BE00BF29C67A696E", + "ESCDerivedFromDataTokenAndContentionFactor": "8AAF04CBA6DC16BFB37CADBA43DCA66C183634CB3DA278DE174556AE6E17CEBB", + "ECCDerivedFromDataTokenAndContentionFactor": "E9580F805E0D07AF384EBA185384F28A49C3DB93AFA4A187A1F4DA129271D82C", + "EDCTwiceDerivedToken": "B39A7EC33FD976EFB8EEBBBF3A265A933E2128D709BB88C77E3D42AA735F697C", + "ESCTwiceDerivedTagToken": "D6F76A9D4767E0889B709517C8CF0412D81874AEB6E6CEBFBDDFF7B013EB7154", + "ESCTwiceDerivedValueToken": "53F0A51A43447B9881D5E79BA4C5F78E80BC2BC6AA42B00C81079EBF4C9D5A7C", "serverCountAndContentionFactorEncryptionToken": "2F30DBCC06B722B60BC1FF018FC28D5FAEE2F222496BE34A264EF3267E811DA0", - "serverZerosEncryptionToken": "986F23F132FF7F14F748AC69373CFC982AD0AD4BAD25BE92008B83AB43E96029" + "serverZerosEncryptionToken": "986F23F132FF7F14F748AC69373CFC982AD0AD4BAD25BE92008B83AB43E96029", + "AnchorPaddingTokenRoot": "4312890F621FE3CA7497C3405DFD8AAF46A578C77F7404D28C12BA853A4D3327" } \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c b/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c index 6e05ba9..3de46d9 100644 --- a/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c +++ b/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c @@ -151,6 +151,7 @@ void _run_state_machine(mongocrypt_ctx_t *ctx, bson_t *result) { while (!done) { state = mongocrypt_ctx_state(ctx); switch (state) { + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: output = mongocrypt_binary_new(); CHECK(mongocrypt_ctx_mongo_op(ctx, output)); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-gcp-auth.c b/ext/libmongocrypt/libmongocrypt/test/test-gcp-auth.c index a22d77c..d1ad533 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-gcp-auth.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-gcp-auth.c @@ -46,7 +46,7 @@ static void _test_createdatakey_with_credentials(_mongocrypt_tester_t *tester) { ASSERT_STREQUAL("oauth2.googleapis.com:443", endpoint); /* Satisfy request. */ - ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/gcp-auth/oauth-response.txt")), kms); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/kms-gcp/oauth-response.txt")), kms); ASSERT_CMPINT((int)mongocrypt_kms_ctx_bytes_needed(kms), ==, 0); kms = mongocrypt_ctx_next_kms_ctx(ctx); @@ -64,7 +64,7 @@ static void _test_createdatakey_with_credentials(_mongocrypt_tester_t *tester) { ASSERT_STREQUAL("cloudkms.googleapis.com:443", endpoint); /* Satisfy request. */ - ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/gcp-auth/encrypt-response.txt")), kms); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/kms-gcp/encrypt-response.txt")), kms); ASSERT_CMPINT((int)mongocrypt_kms_ctx_bytes_needed(kms), ==, 0); kms = mongocrypt_ctx_next_kms_ctx(ctx); @@ -109,7 +109,7 @@ static void _test_encrypt_with_credentials(_mongocrypt_tester_t *tester) { ASSERT_STREQUAL("oauth2.googleapis.com:443", endpoint); /* Satisfy request. */ - ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/gcp-auth/oauth-response.txt")), kms); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/kms-gcp/oauth-response.txt")), kms); ASSERT_CMPINT((int)mongocrypt_kms_ctx_bytes_needed(kms), ==, 0); kms = mongocrypt_ctx_next_kms_ctx(ctx); @@ -127,7 +127,7 @@ static void _test_encrypt_with_credentials(_mongocrypt_tester_t *tester) { ASSERT_STREQUAL("cloudkms.googleapis.com:443", endpoint); /* Satisfy request. */ - ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/gcp-auth/decrypt-response.txt")), kms); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/kms-gcp/decrypt-response.txt")), kms); ASSERT_CMPINT((int)mongocrypt_kms_ctx_bytes_needed(kms), ==, 0); kms = mongocrypt_ctx_next_kms_ctx(ctx); @@ -157,7 +157,7 @@ static void _test_createdatakey_with_accesstoken(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'gcp': {}}")), crypt); mongocrypt_setopt_use_need_kms_credentials_state(crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(kek)), ctx); ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); @@ -175,7 +175,7 @@ static void _test_createdatakey_with_accesstoken(_mongocrypt_tester_t *tester) { ASSERT_STREQUAL("cloudkms.googleapis.com:443", endpoint); /* Satisfy request. */ - ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/gcp-auth/encrypt-response.txt")), kms); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/kms-gcp/encrypt-response.txt")), kms); ASSERT_CMPINT((int)mongocrypt_kms_ctx_bytes_needed(kms), ==, 0); kms = mongocrypt_ctx_next_kms_ctx(ctx); @@ -199,7 +199,7 @@ static void _test_encrypt_with_accesstoken(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'gcp': {}}")), crypt); mongocrypt_setopt_use_need_kms_credentials_state(crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); uuid = mongocrypt_binary_new_from_data((uint8_t *)uuid_data, UUID_LEN); ASSERT_OK(mongocrypt_ctx_setopt_key_id(ctx, uuid), ctx); @@ -227,7 +227,7 @@ static void _test_encrypt_with_accesstoken(_mongocrypt_tester_t *tester) { ASSERT_STREQUAL("cloudkms.googleapis.com:443", endpoint); /* Satisfy request. */ - ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/gcp-auth/decrypt-response.txt")), kms); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/kms-gcp/decrypt-response.txt")), kms); ASSERT_CMPINT((int)mongocrypt_kms_ctx_bytes_needed(kms), ==, 0); kms = mongocrypt_ctx_next_kms_ctx(ctx); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-efc.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-efc.c index 4421667..ee50dfb 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-efc.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-efc.c @@ -34,9 +34,11 @@ static void _test_efc(_mongocrypt_tester_t *tester) { _mongocrypt_buffer_copy_from_hex(&expect_keyId1, "12345678123498761234123456789012"); _mongocrypt_buffer_copy_from_hex(&expect_keyId2, "abcdefab123498761234123456789012"); + const bool use_range_v2 = false; + { _load_test_file(tester, "./test/data/efc/efc-oneField.json", &efc_bson); - ASSERT_OK_STATUS(mc_EncryptedFieldConfig_parse(&efc, &efc_bson, status), status); + ASSERT_OK_STATUS(mc_EncryptedFieldConfig_parse(&efc, &efc_bson, status, use_range_v2), status); ptr = efc.fields; ASSERT(ptr); ASSERT_STREQUAL(ptr->path, "firstName"); @@ -47,7 +49,7 @@ static void _test_efc(_mongocrypt_tester_t *tester) { { _load_test_file(tester, "./test/data/efc/efc-extraField.json", &efc_bson); - ASSERT_OK_STATUS(mc_EncryptedFieldConfig_parse(&efc, &efc_bson, status), status); + ASSERT_OK_STATUS(mc_EncryptedFieldConfig_parse(&efc, &efc_bson, status, use_range_v2), status); ptr = efc.fields; ASSERT(ptr); ASSERT_STREQUAL(ptr->path, "firstName"); @@ -58,7 +60,7 @@ static void _test_efc(_mongocrypt_tester_t *tester) { { _load_test_file(tester, "./test/data/efc/efc-twoFields.json", &efc_bson); - ASSERT_OK_STATUS(mc_EncryptedFieldConfig_parse(&efc, &efc_bson, status), status); + ASSERT_OK_STATUS(mc_EncryptedFieldConfig_parse(&efc, &efc_bson, status, use_range_v2), status); ptr = efc.fields; ASSERT(ptr); ASSERT_STREQUAL(ptr->path, "lastName"); @@ -73,7 +75,7 @@ static void _test_efc(_mongocrypt_tester_t *tester) { { _load_test_file(tester, "./test/data/efc/efc-missingKeyId.json", &efc_bson); - ASSERT_FAILS_STATUS(mc_EncryptedFieldConfig_parse(&efc, &efc_bson, status), + ASSERT_FAILS_STATUS(mc_EncryptedFieldConfig_parse(&efc, &efc_bson, status, use_range_v2), status, "unable to find 'keyId' in 'field' document"); mc_EncryptedFieldConfig_cleanup(&efc); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-find-range-payload-v2.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-find-range-payload-v2.c index e900ce1..79b2036 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-find-range-payload-v2.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-find-range-payload-v2.c @@ -17,6 +17,7 @@ #include #include "mc-fle2-find-range-payload-private-v2.h" +#include "test-mongocrypt-assert-match-bson.h" #include "test-mongocrypt-assert.h" #include "test-mongocrypt.h" @@ -62,7 +63,7 @@ static void _test_FLE2FindRangePayloadV2_roundtrip(_mongocrypt_tester_t *tester) tokenSet.escDerivedToken = expect_escDerivedToken; tokenSet.serverDerivedFromDataToken = expect_serverDerivedFromDataToken; _mc_array_append_val(&payload.payload.value.edgeFindTokenSetArray, tokenSet); - payload.payload.value.maxContentionCounter = (uint64_t)4; + payload.payload.value.maxContentionFactor = (uint64_t)4; } payload.payload.set = true; @@ -72,7 +73,8 @@ static void _test_FLE2FindRangePayloadV2_roundtrip(_mongocrypt_tester_t *tester) payload.secondOperator = expect_secondOperator; bson_init(&out_bson); - mc_FLE2FindRangePayloadV2_serialize(&payload, &out_bson); + const bool use_range_v2 = false; + mc_FLE2FindRangePayloadV2_serialize(&payload, &out_bson, use_range_v2); ASSERT_EQUAL_BSON(&in_bson, &out_bson); @@ -84,6 +86,44 @@ static void _test_FLE2FindRangePayloadV2_roundtrip(_mongocrypt_tester_t *tester) #undef TEST_FIND_RANGE_PAYLOAD_HEX_V2 +static void _test_FLE2FindRangePayloadV2_includes_crypto_params(_mongocrypt_tester_t *tester) { + mc_FLE2FindRangePayloadV2_t payload; + mc_FLE2FindRangePayloadV2_init(&payload); + payload.sparsity = OPT_I64(1); + payload.precision = OPT_I32(2); + payload.trimFactor = OPT_I32(3); + bson_value_t indexMin = {.value.v_int32 = 4, .value_type = BSON_TYPE_INT32}; + bson_value_copy(&indexMin, &payload.indexMin); + bson_value_t indexMax = {.value.v_int32 = 5, .value_type = BSON_TYPE_INT32}; + bson_value_copy(&indexMax, &payload.indexMax); + + // Test crypto params from SERVER-91889 are included in "range" payload. + { + bson_t got = BSON_INITIALIZER; + const bool use_range_v2 = true; + ASSERT(mc_FLE2FindRangePayloadV2_serialize(&payload, &got, use_range_v2)); + _assert_match_bson(&got, TMP_BSON(BSON_STR({"sp" : 1, "pn" : 2, "tf" : 3, "mn" : 4, "mx" : 5}))); + bson_destroy(&got); + } + + // Test crypto params from SERVER-91889 are excluded in "rangePreview" payload. + { + bson_t got = BSON_INITIALIZER; + const bool use_range_v2 = false; + ASSERT(mc_FLE2FindRangePayloadV2_serialize(&payload, &got, use_range_v2)); + _assert_match_bson(&got, TMP_BSON(BSON_STR({ + "sp" : {"$exists" : false}, + "pn" : {"$exists" : false}, + "tf" : {"$exists" : false}, + "mn" : {"$exists" : false}, + "mx" : {"$exists" : false} + }))); + bson_destroy(&got); + } + mc_FLE2FindRangePayloadV2_cleanup(&payload); +} + void _mongocrypt_tester_install_fle2_payload_find_range_v2(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_FLE2FindRangePayloadV2_roundtrip); -} \ No newline at end of file + INSTALL_TEST(_test_FLE2FindRangePayloadV2_includes_crypto_params); +} diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c index 46470b9..af7ba18 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c @@ -14,7 +14,9 @@ * limitations under the License. */ +#include "mc-fle-blob-subtype-private.h" #include "mc-fle2-insert-update-payload-private-v2.h" +#include "test-mongocrypt-assert-match-bson.h" #include "test-mongocrypt.h" #define TEST_IUP_HEX_V2 \ @@ -166,7 +168,81 @@ static void _test_mc_FLE2InsertUpdatePayloadV2_decrypt(_mongocrypt_tester_t *tes #undef TEST_IUP_HEX_V2 +static void _test_mc_FLE2InsertUpdatePayloadV2_includes_crypto_params(_mongocrypt_tester_t *tester) { + mc_FLE2InsertUpdatePayloadV2_t payload; + mc_FLE2InsertUpdatePayloadV2_init(&payload); + payload.sparsity = OPT_I64(1); + payload.precision = OPT_I32(2); + payload.trimFactor = OPT_I32(3); + bson_value_t indexMin = {.value.v_int32 = 4, .value_type = BSON_TYPE_INT32}; + bson_value_copy(&indexMin, &payload.indexMin); + bson_value_t indexMax = {.value.v_int32 = 5, .value_type = BSON_TYPE_INT32}; + bson_value_copy(&indexMax, &payload.indexMax); + + // Test crypto params from SERVER-91889 are included in "range" payload. + { + bson_t got = BSON_INITIALIZER; + const bool use_range_v2 = true; + ASSERT(mc_FLE2InsertUpdatePayloadV2_serializeForRange(&payload, &got, use_range_v2)); + _assert_match_bson(&got, TMP_BSON(BSON_STR({"sp" : 1, "pn" : 2, "tf" : 3, "mn" : 4, "mx" : 5}))); + bson_destroy(&got); + } + + // Test crypto params from SERVER-91889 are excluded in "rangePreview" payload. + { + bson_t got = BSON_INITIALIZER; + const bool use_range_v2 = false; + ASSERT(mc_FLE2InsertUpdatePayloadV2_serializeForRange(&payload, &got, use_range_v2)); + _assert_match_bson(&got, TMP_BSON(BSON_STR({ + "sp" : {"$exists" : false}, + "pn" : {"$exists" : false}, + "tf" : {"$exists" : false}, + "mn" : {"$exists" : false}, + "mx" : {"$exists" : false} + }))); + bson_destroy(&got); + } + mc_FLE2InsertUpdatePayloadV2_cleanup(&payload); +} + +static void _test_mc_FLE2InsertUpdatePayloadV2_parses_crypto_params(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *payload = TEST_FILE("test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json"); + + _mongocrypt_buffer_t payload_buf; + // Unwrap the { "v": } into a `_mongocrypt_buffer_t`. + { + bson_t payload_bson; + ASSERT(_mongocrypt_binary_to_bson(payload, &payload_bson)); + bson_iter_t iter; + ASSERT(bson_iter_init_find(&iter, &payload_bson, "v")); + ASSERT(_mongocrypt_buffer_from_binary_iter(&payload_buf, &iter)); + } + + mc_FLE2InsertUpdatePayloadV2_t got; + mc_FLE2InsertUpdatePayloadV2_init(&got); + + mongocrypt_status_t *status = mongocrypt_status_new(); + ASSERT_OK_STATUS(mc_FLE2InsertUpdatePayloadV2_parse(&got, &payload_buf, status), status); + mongocrypt_status_destroy(status); + + ASSERT(got.sparsity.set); + ASSERT_CMPINT64(got.sparsity.value, ==, 3); + + ASSERT(!got.precision.set); // Payload does not include precision. + + ASSERT(got.trimFactor.set); + ASSERT_CMPINT32(got.trimFactor.value, ==, 4); + + ASSERT(got.indexMin.value_type == BSON_TYPE_INT32); + ASSERT_CMPINT32(got.indexMin.value.v_int32, ==, 0); + + ASSERT(got.indexMax.value_type == BSON_TYPE_INT32); + ASSERT_CMPINT32(got.indexMax.value.v_int32, ==, 1234567); +} + void _mongocrypt_tester_install_fle2_payload_iup_v2(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_FLE2InsertUpdatePayloadV2_parse); INSTALL_TEST(_test_mc_FLE2InsertUpdatePayloadV2_decrypt); + INSTALL_TEST(_test_mc_FLE2InsertUpdatePayloadV2_includes_crypto_params); + INSTALL_TEST(_test_mc_FLE2InsertUpdatePayloadV2_parses_crypto_params); } diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-rfds.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-rfds.c index d6bb560..334e3fb 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-rfds.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-rfds.c @@ -197,7 +197,7 @@ static void test_mc_FLE2RangeFindDriverSpec_to_placeholders(_mongocrypt_tester_t user_key_id.subtype = BSON_SUBTYPE_UUID; index_key_id.subtype = BSON_SUBTYPE_UUID; - int64_t maxContentionCounter = 4; + int64_t maxContentionFactor = 4; int64_t sparsity = 1; int32_t indexMin = 5; int32_t indexMax = 200; @@ -325,7 +325,7 @@ static void test_mc_FLE2RangeFindDriverSpec_to_placeholders(_mongocrypt_tester_t bson_t *range_opts_bson = TMP_BSON("{'min': %d, 'max': %d, 'sparsity': {'$numberLong': '%d'}}", indexMin, indexMax, sparsity); - ASSERT_OK_STATUS(mc_RangeOpts_parse(&range_opts, range_opts_bson, status), status); + ASSERT_OK_STATUS(mc_RangeOpts_parse(&range_opts, range_opts_bson, true /* use_range_v2 */, status), status); for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { testcase_t *test = tests + i; @@ -354,7 +354,7 @@ static void test_mc_FLE2RangeFindDriverSpec_to_placeholders(_mongocrypt_tester_t .secondOp = test->p1.secondOp, .indexMin = TMP_ITER(indexMin), .indexMax = TMP_ITER(indexMax), - .maxContentionCounter = maxContentionCounter, + .maxContentionFactor = maxContentionFactor, .sparsity = sparsity}; ASSERT_OK_STATUS(mc_makeRangeFindPlaceholder(&p1_args_full, &p1, status), status); @@ -373,7 +373,7 @@ static void test_mc_FLE2RangeFindDriverSpec_to_placeholders(_mongocrypt_tester_t .secondOp = test->p2.secondOp, .indexMin = TMP_ITER(indexMin), .indexMax = TMP_ITER(indexMax), - .maxContentionCounter = maxContentionCounter, + .maxContentionFactor = maxContentionFactor, .sparsity = sparsity}; ASSERT_OK_STATUS(mc_makeRangeFindPlaceholder(&p2_args_full, &p2, status), status); @@ -386,7 +386,7 @@ static void test_mc_FLE2RangeFindDriverSpec_to_placeholders(_mongocrypt_tester_t bson_t out = BSON_INITIALIZER; bool ok = mc_FLE2RangeFindDriverSpec_to_placeholders(&spec, &range_opts, - maxContentionCounter, + maxContentionFactor, &user_key_id, &index_key_id, payloadId, diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-range-edge-generation.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-range-edge-generation.c index 7b3531e..a994f4b 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-range-edge-generation.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-range-edge-generation.c @@ -32,6 +32,7 @@ typedef struct { // expectEdges includes a trailing NULL pointer. const char *expectEdges[MAX_INT32_EDGES + 1]; const char *expectError; + int32_t trimFactor; } Int32Test; #undef MAX_INT32_EDGES @@ -62,6 +63,49 @@ static void _test_getEdgesInt32(_mongocrypt_tester_t *tester) { .expectEdges = {"root", "010", "0", "01"}}, {.value = 2, .min = OPT_I32_C(0), .max = OPT_I32_C(7), .sparsity = 2, .expectEdges = {"root", "010", "01"}}, {.value = 1, .sparsity = 0, .expectError = "sparsity must be 1 or larger"}, + {.value = 2, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 1, + .trimFactor = 1, + .expectEdges = {"010", "0", "01"}}, + {.value = 2, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 1, + .trimFactor = 2, + .expectEdges = {"010", "01"}}, + {.value = 2, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 1, + .trimFactor = 3, + .expectError = + "trimFactor must be less than the number of bits (3) used to represent an element of the domain"}, + {.value = 2, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 1, + .trimFactor = -1, + .expectError = "trimFactor must be >= 0"}, + {.value = 2, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 2, + .trimFactor = 0, + .expectEdges = {"root", "010", "01"}}, + {.value = 2, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 2, + .trimFactor = 1, + .expectEdges = {"010", "01"}}, + {.value = 2, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 2, + .trimFactor = 2, + .expectEdges = {"010", "01"}}, #include "data/range-edge-generation/edges_int32.cstruct" }; @@ -71,8 +115,10 @@ static void _test_getEdgesInt32(_mongocrypt_tester_t *tester) { mc_getEdgesInt32_args_t args = {.value = test->value, .min = test->min, .max = test->max, - .sparsity = test->sparsity}; - mc_edges_t *got = mc_getEdgesInt32(args, status); + .sparsity = test->sparsity, + .trimFactor = OPT_I32(test->trimFactor)}; + const bool use_range_v2 = true; + mc_edges_t *got = mc_getEdgesInt32(args, status, use_range_v2); if (test->expectError != NULL) { ASSERT_OR_PRINT_MSG(NULL == got, "expected error, got success"); ASSERT_STATUS_CONTAINS(status, test->expectError); @@ -116,6 +162,7 @@ typedef struct { // expectEdges includes a trailing NULL pointer. const char *expectEdges[MAX_INT64_EDGES + 1]; const char *expectError; + uint32_t trimFactor; } Int64Test; #undef MAX_INT64_EDGES @@ -132,6 +179,25 @@ static void _test_getEdgesInt64(_mongocrypt_tester_t *tester) { .max = OPT_I64_C(7), .sparsity = 2, .expectEdges = {"root", "010", "01"}}, + {.value = INT64_C(2), + .min = OPT_I64_C(0), + .max = OPT_I64_C(7), + .sparsity = 1, + .trimFactor = 1, + .expectEdges = {"010", "0", "01"}}, + {.value = INT64_C(2), + .min = OPT_I64_C(0), + .max = OPT_I64_C(7), + .sparsity = 1, + .trimFactor = 2, + .expectEdges = {"010", "01"}}, + {.value = INT64_C(2), + .min = OPT_I64_C(0), + .max = OPT_I64_C(7), + .sparsity = 1, + .trimFactor = 3, + .expectError = + "trimFactor must be less than the number of bits (3) used to represent an element of the domain"}, {.value = 1, .sparsity = 0, .expectError = "sparsity must be 1 or larger"}, #include "data/range-edge-generation/edges_int64.cstruct" }; @@ -142,8 +208,10 @@ static void _test_getEdgesInt64(_mongocrypt_tester_t *tester) { mc_getEdgesInt64_args_t args = {.value = test->value, .min = test->min, .max = test->max, - .sparsity = test->sparsity}; - mc_edges_t *got = mc_getEdgesInt64(args, status); + .sparsity = test->sparsity, + .trimFactor = OPT_I32(test->trimFactor)}; + const bool use_range_v2 = true; + mc_edges_t *got = mc_getEdgesInt64(args, status, use_range_v2); if (test->expectError != NULL) { ASSERT_OR_PRINT_MSG(NULL == got, "expected error, got success"); ASSERT_STATUS_CONTAINS(status, test->expectError); @@ -181,6 +249,8 @@ static void _test_getEdgesInt64(_mongocrypt_tester_t *tester) { typedef struct { double value; + mc_optional_double_t min; // Unused. Kept for consistency with server test data. + mc_optional_double_t max; // Unused. Kept for consistency with server test data. size_t sparsity; // expectEdges includes a trailing NULL pointer. const char *expectEdges[MAX_DOUBLE_EDGES + 1]; @@ -197,8 +267,12 @@ static void _test_getEdgesDouble(_mongocrypt_tester_t *tester) { for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { mongocrypt_status_t *const status = mongocrypt_status_new(); const DoubleTest *test = tests + i; - mc_getEdgesDouble_args_t args = {.value = test->value, .sparsity = test->sparsity}; - mc_edges_t *got = mc_getEdgesDouble(args, status); + const uint32_t trimFactor = 0; // At present, all test cases expect trimFactor=0. + mc_getEdgesDouble_args_t args = {.value = test->value, + .sparsity = test->sparsity, + .trimFactor = OPT_I32(trimFactor)}; + const bool use_range_v2 = true; + mc_edges_t *got = mc_getEdgesDouble(args, status, use_range_v2); if (test->expectError != NULL) { if (NULL != got) { @@ -258,14 +332,15 @@ static void _test_getEdgesDecimal128(_mongocrypt_tester_t *tester) { for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { const Decimal128Test *test = tests + i; mongocrypt_status_t *const status = mongocrypt_status_new(); - mc_getEdgesDecimal128_args_t args = { - .value = test->value, - // Some edges specify min/max values, but we don't use them (yet) - // .min = test->min, - // .max = test->max, - .sparsity = (size_t)test->sparsity, - }; - mc_edges_t *got = mc_getEdgesDecimal128(args, status); + const uint32_t trimFactor = 0; // At present, all test cases expect trimFactor=0. + mc_getEdgesDecimal128_args_t args = {.value = test->value, + // Some edges specify min/max values, but we don't use them (yet) + // .min = test->min, + // .max = test->max, + .sparsity = (size_t)test->sparsity, + .trimFactor = OPT_I32(trimFactor)}; + const bool use_range_v2 = true; + mc_edges_t *got = mc_getEdgesDecimal128(args, status, use_range_v2); if (test->expectError != NULL) { if (NULL != got) { diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-range-encoding.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-range-encoding.c index 5febc34..27da76d 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-range-encoding.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-range-encoding.c @@ -20,6 +20,7 @@ #include // DBL_MAX #include // INFINITY, NAN +#include typedef struct { mc_getTypeInfo32_args_t args; @@ -193,16 +194,84 @@ static void _test_RangeTest_Encode_Int64(_mongocrypt_tester_t *tester) { } } +#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_uint32_t precision; + 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 @@ -254,43 +323,43 @@ static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { /* Test cases copied from Double_Bounds_Precision ... begin */ {.value = 3.141592653589, - .precision = OPT_U32_C(1), + .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_U32_C(2), + .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_U32_C(3), + .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_U32_C(4), + .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_U32_C(5), + .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_U32_C(6), + .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_U32_C(7), + .precision = OPT_I32_C(7), .min = OPT_DOUBLE_C(-100000), .max = OPT_DOUBLE_C(100000), .expect = 1000031415926, @@ -298,113 +367,184 @@ static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { {.value = 0, .max = OPT_DOUBLE_C(1), .min = OPT_DOUBLE_C(-1), - .precision = OPT_U32_C(3), + .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_U32_C(3), + .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_U32_C(3), + .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_U32_C(3), - .expect = UINT64_C(9223372036854775808), - // Expect precision not to be used. - .expectMax = OPT_U64_C(UINT64_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_U32_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_U32_C(1), + .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_U32_C(2), + .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_U32_C(3), + .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_U32_C(16), - .expect = 31415926535890000, - .expectMax = OPT_U64_C(72057594037927935)}, + .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_U32_C(3), + .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_U32_C(3), - .expect = 15326393489903895421ULL, - // Expect precision not to be used. - .expectMax = OPT_U64_C(UINT64_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_U32_C(3), + .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_U32_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_U32_C(0), + .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_U32_C(2), + .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_U32_C(35), - .expect = 13381399884061196960ULL, - // Expect precision not to be used. - .expectMax = OPT_U64_C(UINT64_MAX)}, + .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_U32_C(1), + .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_U32_C(1), - .expectError = "less than or equal to the maximum value"}}; + .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; @@ -421,13 +561,15 @@ static void _test_RangeTest_Encode_Double(_mongocrypt_tester_t *tester) { 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); + status, + use_range_v2); if (test->expectError) { ASSERT_OR_PRINT_MSG(!ok, "expected error, but got none"); ASSERT_STATUS_CONTAINS(status, test->expectError); @@ -446,11 +588,88 @@ typedef struct { mc_dec128 value; mc_optional_dec128_t min; mc_optional_dec128_t max; - mc_optional_uint32_t precision; + 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) \ @@ -553,29 +772,29 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { ERROR_CASE(MC_DEC128_C(1), OPT_NULLOPT, OPT_MC_DEC128(MC_DEC128_C(2)), - OPT_U32(5), + 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_U32(5), + 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_U32(5), + 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_U32(5), + 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_U32(5), + OPT_I32(5), "Value must be greater than or equal to the minimum value " "and less than or equal to the maximum value"), @@ -608,7 +827,7 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .value = mc_dec128_from_string(Value), \ .min = OPT_MC_DEC128(MC_DEC128_C(-100000)), \ .max = OPT_MC_DEC128(MC_DEC128_C(100000)), \ - .precision = OPT_U32(Precision), \ + .precision = OPT_I32(Precision), \ .expect = MLIB_INT128(Expect), \ } ASSERT_EIBP("3.141592653589E-1", 10, 1000003141592653), @@ -626,7 +845,7 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .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_U32(Precision), \ + .precision = OPT_I32(Precision), \ .expect = mlib_int128_from_string(Expect, NULL), \ } @@ -643,7 +862,7 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .value = mc_dec128_from_string(#Value), \ .min = OPT_MC_DEC128(MC_DEC128_C(-100000)), \ .max = OPT_MC_DEC128(MC_DEC128_C(100000)), \ - .precision = OPT_U32(Precision), \ + .precision = OPT_I32(Precision), \ .expect = MLIB_INT128_CAST(Expect), \ } ASSERT_EIBP(3.141592653589, 1, 1000031), @@ -660,14 +879,41 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { .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_U32(Precision), \ + .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) { \ + (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_U32(Precision), .expect = Expect, \ + .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), @@ -675,16 +921,19 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { ASSERT_EIBB(-1E-33, 1, -1E5, 3, 100000000), - ASSERT_EIBB_OVERFLOW(0, - MC_DEC128_LARGEST_POSITIVE, - MC_DEC128_LARGEST_NEGATIVE, - 3, - mlib_int128_from_string("170141183460469231731687303715884105728", NULL)), - ASSERT_EIBB_OVERFLOW(0, - DBL_MAX, - DBL_MIN, - 3, - mlib_int128_from_string("170141183460469231731687303715884105728", NULL)), + 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), @@ -696,11 +945,12 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { ASSERT_EIBB(-5, -1, -10, 3, 5000), - ASSERT_EIBB_OVERFLOW(1E100, - DBL_MAX, - DBL_MIN, - 3, - mlib_int128_from_string("232572183460469231731687303715884099485", NULL)), + 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), @@ -712,15 +962,24 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { // Test a range that requires > 64 bits. ASSERT_EIBB(5, 18446744073709551616, .1, 1, 49), - // Test a range that requires > 64 bits. - // min has more places after the decimal than precision. - ASSERT_EIBB(5, 18446744073709551616, .01, 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; @@ -738,12 +997,17 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { } fflush(stdout); mc_OSTType_Decimal128 got; - const bool ok = mc_getTypeInfoDecimal128((mc_getTypeInfoDecimal128_args_t){.value = test->value, - .min = test->min, - .max = test->max, - .precision = test->precision}, - &got, - status); + 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); @@ -762,8 +1026,10 @@ static void _test_RangeTest_Encode_Decimal128(_mongocrypt_tester_t *tester) { 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 } diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c index 869ad78..2214c66 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c @@ -19,6 +19,7 @@ #include "mc-array-private.h" #include "mc-check-conversions-private.h" #include "mc-optional-private.h" +#include "mc-range-encoding-private.h" #include "mc-range-mincover-private.h" enum { @@ -37,6 +38,7 @@ typedef struct { mc_optional_int32_t min; mc_optional_int32_t max; size_t sparsity; + uint32_t trimFactor; const char *expectMincoverStrings[MAX_MINCOVER_STRINGS]; const char *expectError; } Int32Test; @@ -61,7 +63,7 @@ typedef struct { size_t sparsity; mc_optional_double_t min; mc_optional_double_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; const char *expectMincoverStrings[MAX_MINCOVER_STRINGS]; const char *expectError; } DoubleTest; @@ -75,7 +77,7 @@ typedef struct { size_t sparsity; mc_optional_dec128_t min; mc_optional_dec128_t max; - mc_optional_uint32_t precision; + mc_optional_int32_t precision; const char *expectMincoverStrings[MAX_MINCOVER_STRINGS]; const char *expectError; } Decimal128Test; @@ -93,19 +95,24 @@ static mc_mincover_t *_test_getMincover32(void *tests, size_t idx, mongocrypt_st Int32Test *test = (Int32Test *)tests + idx; + const bool use_range_v2 = true; return mc_getMincoverInt32((mc_getMincoverInt32_args_t){.lowerBound = test->lowerBound, .includeLowerBound = test->includeLowerBound, .upperBound = test->upperBound, .includeUpperBound = test->includeUpperBound, .min = test->min, .max = test->max, - .sparsity = test->sparsity}, - status); + .sparsity = test->sparsity, + .trimFactor = OPT_I32(test->trimFactor)}, + status, + use_range_v2); } static mc_mincover_t *_test_getMincover64(void *tests, size_t idx, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(tests); + const bool use_range_v2 = true; + const uint32_t trimFactor = 0; // At present, all test cases expect trimFactor=0. Int64Test *const test = (Int64Test *)tests + idx; return mc_getMincoverInt64((mc_getMincoverInt64_args_t){.lowerBound = test->lowerBound, @@ -114,13 +121,17 @@ static mc_mincover_t *_test_getMincover64(void *tests, size_t idx, mongocrypt_st .includeUpperBound = test->includeUpperBound, .min = test->min, .max = test->max, - .sparsity = test->sparsity}, - status); + .sparsity = test->sparsity, + .trimFactor = OPT_I32(trimFactor)}, + status, + use_range_v2); } static mc_mincover_t *_test_getMincoverDouble_helper(void *tests, size_t idx, mongocrypt_status_t *status) { BSON_ASSERT_PARAM(tests); + const bool use_range_v2 = true; + const uint32_t trimFactor = 0; // At present, all test cases expect trimFactor=0. DoubleTest *const test = (DoubleTest *)tests + idx; return mc_getMincoverDouble( @@ -131,8 +142,10 @@ static mc_mincover_t *_test_getMincoverDouble_helper(void *tests, size_t idx, mo .sparsity = test->sparsity, .min = test->precision.set ? test->min : (mc_optional_double_t){0}, .max = test->precision.set ? test->max : (mc_optional_double_t){0}, - .precision = test->precision}, - status); + .precision = test->precision, + .trimFactor = OPT_I32(trimFactor)}, + status, + use_range_v2); } #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT @@ -141,6 +154,8 @@ static mc_mincover_t *_test_getMincoverDecimal128_helper(void *tests, size_t idx Decimal128Test *const test = (Decimal128Test *)tests + idx; + const bool use_range_v2 = true; + const uint32_t trimFactor = 0; // At present, all test cases expect trimFactor=0. return mc_getMincoverDecimal128( (mc_getMincoverDecimal128_args_t){.lowerBound = test->lowerBound, .includeLowerBound = test->includeLowerBound, @@ -149,8 +164,10 @@ static mc_mincover_t *_test_getMincoverDecimal128_helper(void *tests, size_t idx .sparsity = test->sparsity, .min = test->precision.set ? test->min : (mc_optional_dec128_t){0}, .max = test->precision.set ? test->max : (mc_optional_dec128_t){0}, - .precision = test->precision}, - status); + .precision = test->precision, + .trimFactor = OPT_I32(trimFactor)}, + status, + use_range_v2); } #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT @@ -166,13 +183,42 @@ static const char *_test_expectError64(void *tests, size_t idx) { static const char *_test_expectErrorDouble(void *tests, size_t idx) { BSON_ASSERT_PARAM(tests); - return ((DoubleTest *)tests + idx)->expectError; + DoubleTest *test = ((DoubleTest *)tests + idx); + if (test->min.set && test->max.set && test->precision.set) { + // Expect an error for tests including an invalid min/max/precision. + uint32_t ignored; + mongocrypt_status_t *const status = mongocrypt_status_new(); + if (!mc_canUsePrecisionModeDouble(test->min.value, test->max.value, test->precision.value, &ignored, status)) { + if (!mongocrypt_status_ok(status)) { + return mongocrypt_status_message(status, NULL); + } + + return "The domain of double values specified by the min, max, and precision cannot be represented in " + "fewer than 64 bits"; + } + mongocrypt_status_destroy(status); + } + return test->expectError; } #if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT static const char *_test_expectErrorDecimal128(void *tests, size_t idx) { BSON_ASSERT_PARAM(tests); - return ((Decimal128Test *)tests + idx)->expectError; + Decimal128Test *test = ((Decimal128Test *)tests + idx); + if (test->min.set && test->max.set && test->precision.set) { + // Expect an error for tests including an invalid min/max/precision. + uint32_t ignored; + mongocrypt_status_t *const status = mongocrypt_status_new(); + if (!mc_canUsePrecisionModeDecimal(test->min.value, test->max.value, test->precision.value, &ignored, status)) { + if (!mongocrypt_status_ok(status)) { + return mongocrypt_status_message(status, NULL); + } + + return "The domain of decimal values specified by the min, max, and precision cannot be represented in " + "fewer than 128 bits"; + } + } + return test->expectError; } #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT @@ -429,6 +475,42 @@ static void _test_getMincoverInt32(_mongocrypt_tester_t *tester) { .max = OPT_I32_C(7), .sparsity = 1, .expectError = "less than or equal to the maximum value"}, + {.lowerBound = 0, + .includeLowerBound = true, + .upperBound = 7, + .includeUpperBound = true, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 1, + .expectMincoverStrings = {"root"}}, + {.lowerBound = 0, + .includeLowerBound = true, + .upperBound = 7, + .includeUpperBound = true, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 1, + .trimFactor = 1, + .expectMincoverStrings = {"0", "1"}}, + {.lowerBound = 0, + .includeLowerBound = true, + .upperBound = 7, + .includeUpperBound = true, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 1, + .trimFactor = 2, + .expectMincoverStrings = {"00", "01", "10", "11"}}, + {.lowerBound = 0, + .includeLowerBound = true, + .upperBound = 7, + .includeUpperBound = true, + .min = OPT_I32_C(0), + .max = OPT_I32_C(7), + .sparsity = 1, + .trimFactor = 3, + .expectError = + "Trim factor must be less than the number of bits (3) used to represent an element of the domain"}, #include "./data/range-min-cover/mincover_int32.cstruct" diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-rangeopts.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-rangeopts.c index 5e2e841..ea9ce60 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-rangeopts.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-rangeopts.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "mc-range-encoding-private.h" #include "mc-rangeopts-private.h" #include "test-mongocrypt.h" @@ -28,6 +29,8 @@ static void test_mc_RangeOpts_parse(_mongocrypt_tester_t *tester) { mc_optional_int32_t expectMax; int64_t expectSparsity; mc_optional_uint32_t expectPrecision; + mc_optional_int32_t expectTrimFactor; + bool useRangeV2; } testcase; testcase tests[] = { @@ -39,9 +42,6 @@ static void test_mc_RangeOpts_parse(_mongocrypt_tester_t *tester) { {.desc = "Errors if precision is set with int min/max", .in = RAW_STRING({"min" : 123, "max" : 456, "precision" : 2, "sparsity" : {"$numberLong" : "1"}}), .expectError = "expected 'precision' to be set with double or decimal128 index"}, - {.desc = "Errors on missing fields", - .in = RAW_STRING({"min" : 123, "max" : 456}), - .expectError = "Missing field 'sparsity'"}, {.desc = "Errors on extra fields", .in = RAW_STRING({"min" : 123, "max" : 456, "sparsity" : {"$numberLong" : "1"}, "foo" : 1}), .expectError = "Unrecognized field: 'foo'"}, @@ -62,6 +62,25 @@ static void test_mc_RangeOpts_parse(_mongocrypt_tester_t *tester) { {.desc = "Requires precision for double when only min is set", .in = RAW_STRING({"min" : 0.0, "sparsity" : {"$numberLong" : "1"}}), .expectError = "expected 'precision'"}, + // Once `use_range_v2` is default true, this test may be removed. + {.desc = "Fails when trim factor is set but Range V2 is disabled", + .in = RAW_STRING({"trimFactor" : 1, "sparsity" : {"$numberLong" : "1"}}), + .expectError = "'trimFactor' is not supported for QE range v1"}, + {.desc = "Works when trim factor is set and Range V2 is enabled", + .in = RAW_STRING({"trimFactor" : 1, "sparsity" : {"$numberLong" : "1"}}), + .useRangeV2 = true, + .expectSparsity = 1, + .expectTrimFactor = OPT_I32(1)}, + {.desc = "Does not require sparsity", + .in = RAW_STRING({"min" : 123, "max" : 456}), + .useRangeV2 = true, + .expectSparsity = mc_FLERangeSparsityDefault, + .expectMin = OPT_I32_C(123), + .expectMax = OPT_I32_C(456)}, + {.desc = "Errors on negative trim factor", + .in = RAW_STRING({"trimFactor" : -1, "sparsity" : {"$numberLong" : "1"}}), + .useRangeV2 = true, + .expectError = "'trimFactor' must be non-negative"}, }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { @@ -69,7 +88,7 @@ static void test_mc_RangeOpts_parse(_mongocrypt_tester_t *tester) { mongocrypt_status_t *status = mongocrypt_status_new(); mc_RangeOpts_t ro; printf("running test_mc_RangeOpts_parse subtest: %s\n", test->desc); - bool ret = mc_RangeOpts_parse(&ro, TMP_BSON(test->in), status); + bool ret = mc_RangeOpts_parse(&ro, TMP_BSON(test->in), test->useRangeV2, status); if (!test->expectError) { ASSERT_OK_STATUS(ret, status); ASSERT_CMPINT(test->expectMin.set, ==, ro.min.set); @@ -83,6 +102,8 @@ static void test_mc_RangeOpts_parse(_mongocrypt_tester_t *tester) { ASSERT_CMPINT64(test->expectSparsity, ==, ro.sparsity); ASSERT_CMPINT(test->expectPrecision.set, ==, ro.precision.set); ASSERT_CMPINT(test->expectPrecision.value, ==, ro.precision.value); + ASSERT_CMPINT(test->expectTrimFactor.set, ==, ro.trimFactor.set); + ASSERT_CMPINT(test->expectTrimFactor.value, ==, ro.trimFactor.value); } else { ASSERT_FAILS_STATUS(ret, status, test->expectError); } @@ -98,6 +119,8 @@ static void test_mc_RangeOpts_to_FLE2RangeInsertSpec(_mongocrypt_tester_t *teste const char *v; const char *expectError; const char *expect; + // Most of the tests are for trim factor, so range V2 is default enabled. + bool disableRangeV2; } testcase; testcase tests[] = { @@ -105,6 +128,11 @@ static void test_mc_RangeOpts_to_FLE2RangeInsertSpec(_mongocrypt_tester_t *teste .in = RAW_STRING({"min" : 123, "max" : 456, "sparsity" : {"$numberLong" : "1"}}), .v = RAW_STRING({"v" : 789}), .expect = RAW_STRING({"v" : {"v" : 789, "min" : 123, "max" : 456}})}, + {.desc = "Trim factor not appended if range V2 disabled", + .in = RAW_STRING({"min" : 123, "max" : 456, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 789}), + .disableRangeV2 = true, + .expect = RAW_STRING({"v" : {"v" : 789, "min" : 123, "max" : 456}})}, {.desc = "Works with precision", .in = RAW_STRING({"min" : 123.0, "max" : 456.0, "precision" : 2, "sparsity" : {"$numberLong" : "1"}}), .v = RAW_STRING({"v" : 789.0}), @@ -112,16 +140,186 @@ static void test_mc_RangeOpts_to_FLE2RangeInsertSpec(_mongocrypt_tester_t *teste {.desc = "Errors with missing 'v'", .in = RAW_STRING({"min" : 123, "max" : 456, "sparsity" : {"$numberLong" : "1"}}), .v = RAW_STRING({"foo" : "bar"}), - .expectError = "Unable to find 'v'"}}; + .expectError = "Unable to find 'v'"}, + // Tests of trim factor + {.desc = "tf = 0 works", + .in = RAW_STRING({"trimFactor" : 0, "min" : 0, "max" : 1, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0}), + .expect = RAW_STRING({"v" : {"v" : 0, "min" : 0, "max" : 1, "trimFactor" : 0}})}, + {.desc = "tf = 1 fails when domain size is 2 = 2^1", + .in = RAW_STRING({"trimFactor" : 1, "min" : 0, "max" : 1, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0}), + .expectError = "Trim factor (1) must be less than the total number of bits (1) used to represent any element " + "in the domain."}, + {.desc = "tf = 1 works when domain size is 3 > 2^1", + .in = RAW_STRING({"trimFactor" : 1, "min" : 0, "max" : 2, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0}), + .expect = RAW_STRING({"v" : {"v" : 0, "min" : 0, "max" : 2, "trimFactor" : 1}})}, + {.desc = "tf = 2 fails when domain size is 3 <= 2^2", + .in = RAW_STRING({"trimFactor" : 2, "min" : 0, "max" : 2, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0}), + .expectError = "Trim factor (2) must be less than the total number of bits (2) used to represent any element " + "in the domain."}, + + // min = INT32_MIN, max = INT32_MAX + {.desc = "tf = 31 works for unbounded int32 (domain size = 2^32)", + .in = RAW_STRING( + {"trimFactor" : 31, "min" : -2147483648, "max" : 2147483647, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0}), + .expect = RAW_STRING({"v" : {"v" : 0, "min" : -2147483648, "max" : 2147483647, "trimFactor" : 31}})}, + {.desc = "tf = 32 fails for unbounded int32 (domain size = 2^32)", + .in = RAW_STRING( + {"trimFactor" : 32, "min" : -2147483648, "max" : 2147483647, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0}), + .expectError = "Trim factor (32) must be less than the total number of bits (32) used to represent any " + "element in the domain."}, + + // min = INT64_MIN, max = INT64_MAX + {.desc = "tf = 63 works for int64 with no min/max (domain size = 2^64)", + .in = RAW_STRING({ + "trimFactor" : 63, + "min" : -9223372036854775808, + "max" : 9223372036854775807, + "sparsity" : {"$numberLong" : "1"} + }), + .v = RAW_STRING({"v" : {"$numberLong" : "0"}}), + .expect = RAW_STRING({ + "v" : { + "v" : {"$numberLong" : "0"}, + "min" : {"$numberLong" : "-9223372036854775808"}, + "max" : {"$numberLong" : "9223372036854775807"}, + "trimFactor" : 63 + } + })}, + {.desc = "tf = 64 fails for int64 with no min/max (domain size = 2^64)", + .in = RAW_STRING({ + "trimFactor" : 64, + "min" : -9223372036854775808, + "max" : 9223372036854775807, + "sparsity" : {"$numberLong" : "1"} + }), + .v = RAW_STRING({"v" : {"$numberLong" : "0"}}), + .expectError = "Trim factor (64) must be less than the total number of bits (64) used to represent any " + "element in the domain."}, + + {.desc = "tf = 63 works for date with no min/max (domain size = 2^64)", + .in = RAW_STRING({ + "trimFactor" : 63, + "min" : {"$date" : {"$numberLong" : "-9223372036854775808"}}, + "max" : {"$date" : {"$numberLong" : "9223372036854775807"}}, + "sparsity" : {"$numberLong" : "1"} + }), + .v = RAW_STRING({"v" : {"$date" : {"$numberLong" : "0"}}}), + .expect = RAW_STRING({ + "v" : { + "v" : {"$date" : {"$numberLong" : "0"}}, + "min" : {"$date" : {"$numberLong" : "-9223372036854775808"}}, + "max" : {"$date" : {"$numberLong" : "9223372036854775807"}}, + "trimFactor" : 63 + } + })}, + {.desc = "tf = 64 fails for date with no min/max (domain size = 2^64)", + .in = RAW_STRING({ + "trimFactor" : 64, + "min" : {"$date" : {"$numberLong" : "-9223372036854775808"}}, + "max" : {"$date" : {"$numberLong" : "9223372036854775807"}}, + "sparsity" : {"$numberLong" : "1"} + }), + .v = RAW_STRING({"v" : {"$date" : {"$numberLong" : "0"}}}), + .expectError = "Trim factor (64) must be less than the total number of bits (64) used to represent any " + "element in the domain."}, + + {.desc = "tf bound check passes correctly for double with min, max, precision set (tf = 9, 2^9 < domain size < " + "2^10)", + .in = RAW_STRING( + {"trimFactor" : 9, "min" : 0.0, "max" : 100.0, "precision" : 1, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0.0}), + .expect = RAW_STRING({"v" : {"v" : 0.0, "min" : 0.0, "max" : 100.0, "precision" : 1, "trimFactor" : 9}})}, + {.desc = "tf bound check fails correctly for double with min, max, precision set (tf = 10, domain size < 2^10)", + .in = RAW_STRING( + {"trimFactor" : 10, "min" : 0.0, "max" : 100.0, "precision" : 1, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0.0}), + .expectError = "Trim factor (10) must be less than the total number of bits (10) used to represent any " + "element in the domain."}, + + {.desc = "tf = 63 works for unbounded double (domain size = 2^64)", + .in = RAW_STRING({"trimFactor" : 63, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0.0}), + // note - when min and max are unset, they are added into the insert spec. + .expect = RAW_STRING({ + "v" : { + "v" : 0.0, + "min" : {"$numberDouble" : "-1.7976931348623157081e+308"}, + "max" : {"$numberDouble" : "1.7976931348623157081e+308"}, + "trimFactor" : 63 + } + })}, + {.desc = "tf = 64 fails for unbounded double (domain size = 2^64))", + .in = RAW_STRING({"trimFactor" : 64, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : 0.0}), + .expectError = "Trim factor (64) must be less than the total number of bits (64) used to represent any " + "element in the domain."}, + +#if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT + {.desc = "tf bound check passes correctly for decimal with min, max, precision set (tf = 9, 2^9 < domain size " + "< 2^10)", + .in = RAW_STRING({ + "trimFactor" : 9, + "min" : {"$numberDecimal" : "0"}, + "max" : {"$numberDecimal" : "100"}, + "precision" : 1, + "sparsity" : {"$numberLong" : "1"} + }), + .v = RAW_STRING({"v" : {"$numberDecimal" : "0"}}), + .expect = RAW_STRING({ + "v" : { + "v" : {"$numberDecimal" : "0"}, + "min" : {"$numberDecimal" : "0"}, + "max" : {"$numberDecimal" : "100"}, + "precision" : 1, + "trimFactor" : 9 + } + })}, + {.desc = + "tf bound check fails correctly for decimal with min, max, precision set (tf = 10, domain size < 2^10)", + .in = RAW_STRING({ + "trimFactor" : 10, + "min" : {"$numberDecimal" : "0"}, + "max" : {"$numberDecimal" : "100"}, + "precision" : 1, + "sparsity" : {"$numberLong" : "1"} + }), + .v = RAW_STRING({"v" : {"$numberDecimal" : "0"}}), + .expectError = "Trim factor (10) must be less than the total number of bits (10) used to represent any " + "element in the domain."}, + + {.desc = "tf = 127 works for unbounded decimal (domain size = 2^128)", + .in = RAW_STRING({"trimFactor" : 127, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : {"$numberDecimal" : "0"}}), + .expect = RAW_STRING({ + "v" : { + "v" : {"$numberDecimal" : "0"}, + "min" : {"$numberDecimal" : "-9.999999999999999999999999999999999E+6144"}, + "max" : {"$numberDecimal" : "9.999999999999999999999999999999999E+6144"}, + "trimFactor" : 127 + } + })}, + {.desc = "tf = 128 fails for unbounded decimal (domain size = 2^128)", + .in = RAW_STRING({"trimFactor" : 128, "sparsity" : {"$numberLong" : "1"}}), + .v = RAW_STRING({"v" : {"$numberDecimal" : "0"}}), + .expectError = "Trim factor (128) must be less than the total number of bits (128) used to represent any " + "element in the domain."}, +#endif + }; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { testcase *test = tests + i; mongocrypt_status_t *status = mongocrypt_status_new(); mc_RangeOpts_t ro; printf("running test_mc_RangeOpts_to_FLE2RangeInsertSpec subtest: %s\n", test->desc); - ASSERT_OK_STATUS(mc_RangeOpts_parse(&ro, TMP_BSON(test->in), status), status); + ASSERT_OK_STATUS(mc_RangeOpts_parse(&ro, TMP_BSON(test->in), !test->disableRangeV2, status), status); bson_t out = BSON_INITIALIZER; - bool ret = mc_RangeOpts_to_FLE2RangeInsertSpec(&ro, TMP_BSON(test->v), &out, status); + bool ret = mc_RangeOpts_to_FLE2RangeInsertSpec(&ro, TMP_BSON(test->v), &out, !test->disableRangeV2, status); if (!test->expectError) { ASSERT_OK_STATUS(ret, status); ASSERT_EQUAL_BSON(TMP_BSON(test->expect), &out); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mc-tokens.c b/ext/libmongocrypt/libmongocrypt/test/test-mc-tokens.c index 6e99341..a536141 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mc-tokens.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mc-tokens.c @@ -14,6 +14,7 @@ * limitations under the License. */ #include "mc-tokens-private.h" +#include "test-mongocrypt-assert.h" #include "test-mongocrypt.h" #define FOREACH_FIELD(F) \ @@ -30,17 +31,21 @@ F(ESCDerivedFromDataToken) \ F(ECCDerivedFromDataToken) \ F(serverDerivedFromDataToken) \ - F(EDCDerivedFromDataTokenAndCounter) \ - F(ESCDerivedFromDataTokenAndCounter) \ - F(ECCDerivedFromDataTokenAndCounter) \ + F(EDCDerivedFromDataTokenAndContentionFactor) \ + F(ESCDerivedFromDataTokenAndContentionFactor) \ + F(ECCDerivedFromDataTokenAndContentionFactor) \ + F(EDCTwiceDerivedToken) \ + F(ESCTwiceDerivedTagToken) \ + F(ESCTwiceDerivedValueToken) \ F(serverCountAndContentionFactorEncryptionToken) \ - F(serverZerosEncryptionToken) + F(serverZerosEncryptionToken) \ + F(AnchorPaddingTokenRoot) typedef struct { #define DECLARE_FIELD(f) _mongocrypt_buffer_t f; FOREACH_FIELD(DECLARE_FIELD) #undef DECLARE_FIELD - uint64_t counter; + uint64_t contentionFactor; } _mc_token_test; static void _mc_token_test_cleanup(_mc_token_test *test) { @@ -64,7 +69,7 @@ static void _mc_token_test_run(_mongocrypt_tester_t *tester, const char *path) { ASSERT(bson_init_static(&test_bson, test_bin->data, test_bin->len)); ASSERT(bson_validate(&test_bson, BSON_VALIDATE_NONE, NULL)); - bool hasCounter = false; + bool hasContentionFactor = false; _mc_token_test test = {{0}}; bson_iter_t it; ASSERT(bson_iter_init(&it, &test_bson)); @@ -83,11 +88,11 @@ static void _mc_token_test_run(_mongocrypt_tester_t *tester, const char *path) { FOREACH_FIELD(PARSE_FIELD) #undef PARSE_FIELD /* else */ - if (!strcmp(field, "counter")) { - ASSERT_OR_PRINT_MSG(!hasCounter, "Duplicate field 'counter' in test"); + if (!strcmp(field, "contentionFactor")) { + ASSERT_OR_PRINT_MSG(!hasContentionFactor, "Duplicate field 'contentionFactor' in test"); ASSERT(BSON_ITER_HOLDS_INT32(&it) || BSON_ITER_HOLDS_INT64(&it)); - test.counter = bson_iter_as_int64(&it); - hasCounter = true; + test.contentionFactor = bson_iter_as_int64(&it); + hasContentionFactor = true; } else { TEST_ERROR("Unknown field '%s'", field); } @@ -96,7 +101,7 @@ static void _mc_token_test_run(_mongocrypt_tester_t *tester, const char *path) { #define CHECK_FIELD(f) ASSERT_OR_PRINT_MSG(test.f.data, "Missing field '" #f "' in test"); FOREACH_FIELD(CHECK_FIELD) #undef CHECK_FIELD - ASSERT_OR_PRINT_MSG(hasCounter, "Missing field 'counter' in test"); + ASSERT_OR_PRINT_MSG(hasContentionFactor, "Missing field 'contentionFactor' in test"); // Run the actual test. mongocrypt_status_t *status = mongocrypt_status_new(); @@ -133,25 +138,37 @@ static void _mc_token_test_run(_mongocrypt_tester_t *tester, const char *path) { TEST_COLL_TOKEN(ECOC) #undef TEST_COLL_TOKEN -// (EDC|ESC|ECC)DerivedFromDataToken(AndCounter)? +// (EDC|ESC|ECC)DerivedFromDataToken(AndContentionFactor)? #define TEST_DERIVED(Name) \ mc_##Name##DerivedFromDataToken_t *Name##DerivedFromDataToken = \ mc_##Name##DerivedFromDataToken_new(crypt->crypto, Name##Token, &test.value, status); \ ASSERT_OR_PRINT(Name##DerivedFromDataToken, status); \ ASSERT_CMPBUF(*mc_##Name##DerivedFromDataToken_get(Name##DerivedFromDataToken), test.Name##DerivedFromDataToken); \ - mc_##Name##DerivedFromDataTokenAndCounter_t *Name##DerivedFromDataTokenAndCounter = \ - mc_##Name##DerivedFromDataTokenAndCounter_new(crypt->crypto, \ - Name##DerivedFromDataToken, \ - test.counter, \ - status); \ - ASSERT_OR_PRINT(Name##DerivedFromDataTokenAndCounter, status); \ - ASSERT_CMPBUF(*mc_##Name##DerivedFromDataTokenAndCounter_get(Name##DerivedFromDataTokenAndCounter), \ - test.Name##DerivedFromDataTokenAndCounter); + mc_##Name##DerivedFromDataTokenAndContentionFactor_t *Name##DerivedFromDataTokenAndContentionFactor = \ + mc_##Name##DerivedFromDataTokenAndContentionFactor_new(crypt->crypto, \ + Name##DerivedFromDataToken, \ + test.contentionFactor, \ + status); \ + ASSERT_OR_PRINT(Name##DerivedFromDataTokenAndContentionFactor, status); \ + ASSERT_CMPBUF( \ + *mc_##Name##DerivedFromDataTokenAndContentionFactor_get(Name##DerivedFromDataTokenAndContentionFactor), \ + test.Name##DerivedFromDataTokenAndContentionFactor); TEST_DERIVED(EDC) TEST_DERIVED(ESC) TEST_DERIVED(ECC) #undef TEST_DERIVED_FROM_DATA_TOKEN +// (EDC|ESC)TwiceDerivedToken(Tag|Value)? +#define TEST_TWICE(Name, Suffix) \ + mc_##Name##TwiceDerived##Suffix##_t *Name##TwiceDerived##Suffix = \ + mc_##Name##TwiceDerived##Suffix##_new(crypt->crypto, Name##DerivedFromDataTokenAndContentionFactor, status); \ + ASSERT_OR_PRINT(Name##TwiceDerived##Suffix, status); \ + ASSERT_CMPBUF(*mc_##Name##TwiceDerived##Suffix##_get(Name##TwiceDerived##Suffix), test.Name##TwiceDerived##Suffix); + TEST_TWICE(EDC, Token); + TEST_TWICE(ESC, TagToken); + TEST_TWICE(ESC, ValueToken); +#undef TEST_TWICE + // ServerDerivedFromDataToken mc_ServerDerivedFromDataToken_t *serverDerivedFromDataToken = mc_ServerDerivedFromDataToken_new(crypt->crypto, serverTokenDerivationLevel1Token, &test.value, status); @@ -171,13 +188,22 @@ static void _mc_token_test_run(_mongocrypt_tester_t *tester, const char *path) { ASSERT_OR_PRINT(serverZeros, status); ASSERT_CMPBUF(*mc_ServerZerosEncryptionToken_get(serverZeros), test.serverZerosEncryptionToken); + // AnchorPaddingTokenRoot + mc_AnchorPaddingTokenRoot_t *padding = mc_AnchorPaddingTokenRoot_new(crypt->crypto, ESCToken, status); + ASSERT_OR_PRINT(padding, status); + ASSERT_CMPBUF(*mc_AnchorPaddingTokenRoot_get(padding), test.AnchorPaddingTokenRoot); + // Done. + mc_AnchorPaddingTokenRoot_destroy(padding); mc_ServerZerosEncryptionToken_destroy(serverZeros); mc_ServerCountAndContentionFactorEncryptionToken_destroy(serverCACFET); mc_ServerDerivedFromDataToken_destroy(serverDerivedFromDataToken); - mc_ECCDerivedFromDataTokenAndCounter_destroy(ECCDerivedFromDataTokenAndCounter); - mc_ESCDerivedFromDataTokenAndCounter_destroy(ESCDerivedFromDataTokenAndCounter); - mc_EDCDerivedFromDataTokenAndCounter_destroy(EDCDerivedFromDataTokenAndCounter); + mc_ESCTwiceDerivedValueToken_destroy(ESCTwiceDerivedValueToken); + mc_ESCTwiceDerivedTagToken_destroy(ESCTwiceDerivedTagToken); + mc_EDCTwiceDerivedToken_destroy(EDCTwiceDerivedToken); + mc_ECCDerivedFromDataTokenAndContentionFactor_destroy(ECCDerivedFromDataTokenAndContentionFactor); + mc_ESCDerivedFromDataTokenAndContentionFactor_destroy(ESCDerivedFromDataTokenAndContentionFactor); + mc_EDCDerivedFromDataTokenAndContentionFactor_destroy(EDCDerivedFromDataTokenAndContentionFactor); mc_ECCDerivedFromDataToken_destroy(ECCDerivedFromDataToken); mc_ESCDerivedFromDataToken_destroy(ESCDerivedFromDataToken); mc_EDCDerivedFromDataToken_destroy(EDCDerivedFromDataToken); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.c index 6f2e380..4230c0f 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.c @@ -360,7 +360,7 @@ bool match_bson_with_ctx(const bson_t *doc, const bson_t *pattern, match_ctx_t * goto fail; } } else if (!found) { - match_err(&derived, "not found"); + match_err(&derived, "key '%s' not found", key); goto fail; } else if (is_empty_operator) { if (empty != is_empty_doc_or_array(&doc_value)) { @@ -637,6 +637,10 @@ static bool match_bson_arrays(const bson_t *array, const bson_t *pattern, match_ derive(ctx, &derived, bson_iter_key(&array_iter)); if (!match_bson_value(array_value, pattern_value, &derived)) { + // Propagate error message. + if (strlen(derived.errmsg) > 0) { + memcpy(ctx->errmsg, derived.errmsg, sizeof(derived.errmsg)); + } return false; } } @@ -884,23 +888,16 @@ const char *_mongoc_bson_type_to_str(bson_type_t t) { } } -void _assert_match_bson(const bson_t *doc, const bson_t *pattern) { - match_ctx_t ctx; - - memset(&ctx, 0, sizeof(match_ctx_t)); - if (!match_bson_with_ctx(doc, pattern, &ctx)) { - char *doc_str = doc ? bson_as_json(doc, NULL) : NULL; - char *pattern_str = bson_as_json(pattern, NULL); - - TEST_ERROR("ASSERT_MATCH failed with document:\n\n" - "%s\n" - "pattern:\n%s\n" - "%s\n", - doc_str ? doc_str : "{}", - pattern_str, - ctx.errmsg); - - bson_free(doc_str); - bson_free(pattern_str); +bool _check_match_bson(const bson_t *doc, const bson_t *pattern, char *errmsg, size_t errmsg_len) { + // Set `retain_dots_in_keys` to interpret a pattern key "db.test" as a key, rather than a key path. + match_ctx_t ctx = {.retain_dots_in_keys = true}; + bool matched = match_bson_with_ctx(doc, pattern, &ctx); + if (matched) { + bson_strncpy(errmsg, "", errmsg_len); + } else { + if (matched) { + bson_strncpy(errmsg, ctx.errmsg, errmsg_len); + } } + return matched; } diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.h b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.h index 720f509..12bfb81 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.h +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.h @@ -20,6 +20,27 @@ #include /* Copied from libmongoc. */ -void _assert_match_bson(const bson_t *doc, const bson_t *pattern); +bool _check_match_bson(const bson_t *doc, const bson_t *pattern, char *errmsg, size_t errmsg_len); + +#define _assert_match_bson(doc, pattern) \ + if (1) { \ + char errmsg[1024] = ""; \ + if (!_check_match_bson(doc, pattern, errmsg, sizeof(errmsg))) { \ + char *doc_str = bson_as_json(doc, NULL); \ + char *pattern_str = bson_as_json(pattern, NULL); \ + \ + TEST_ERROR("ASSERT_MATCH failed with document:\n\n" \ + "%s\n" \ + "pattern:\n%s\n" \ + "%s\n", \ + doc_str ? doc_str : "{}", \ + pattern_str, \ + errmsg); \ + \ + bson_free(doc_str); \ + bson_free(pattern_str); \ + } \ + } else \ + (void)0 #endif /* TEST_MONGOCRYPT_ASSERT_MATCH_BSON_H */ diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache-oauth.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache-oauth.c index 75c92d4..2022bc2 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache-oauth.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache-oauth.c @@ -18,38 +18,121 @@ #include "test-mongocrypt.h" static void _test_cache_oauth_expiration(_mongocrypt_tester_t *tester) { - _mongocrypt_cache_oauth_t *cache; + mc_mapof_kmsid_to_token_t *cache; char *token; bool ret; mongocrypt_status_t *status; - cache = _mongocrypt_cache_oauth_new(); - token = _mongocrypt_cache_oauth_get(cache); + cache = mc_mapof_kmsid_to_token_new(); + token = mc_mapof_kmsid_to_token_get_token(cache, "aws"); BSON_ASSERT(!token); status = mongocrypt_status_new(); - ret = _mongocrypt_cache_oauth_add(cache, TMP_BSON("{'expires_in': 0, 'access_token': 'foo'}"), status); + ret = mc_mapof_kmsid_to_token_add_response(cache, + "aws", + TMP_BSON("{'expires_in': 0, 'access_token': 'foo'}"), + status); ASSERT_OR_PRINT(ret, status); - /* Attempting to get the token will purge the new token from the cache. */ - token = _mongocrypt_cache_oauth_get(cache); + /* Does not return expired token. */ + token = mc_mapof_kmsid_to_token_get_token(cache, "aws"); BSON_ASSERT(!token); /* Attempt to get again, to ensure MONGOCRYPT-321 is fixed. */ - token = _mongocrypt_cache_oauth_get(cache); + token = mc_mapof_kmsid_to_token_get_token(cache, "aws"); BSON_ASSERT(!token); /* Add an unexpired token. */ - ret = _mongocrypt_cache_oauth_add(cache, TMP_BSON("{'expires_in': 1000, 'access_token': 'bar'}"), status); + ret = mc_mapof_kmsid_to_token_add_response(cache, + "aws", + TMP_BSON("{'expires_in': 1000, 'access_token': 'bar'}"), + status); ASSERT_OR_PRINT(ret, status); - token = _mongocrypt_cache_oauth_get(cache); + token = mc_mapof_kmsid_to_token_get_token(cache, "aws"); ASSERT_STREQUAL(token, "bar"); bson_free(token); - _mongocrypt_cache_oauth_destroy(cache); + mc_mapof_kmsid_to_token_destroy(cache); + mongocrypt_status_destroy(status); +} + +#define BSON_STR(...) #__VA_ARGS__ + +static void test_mc_mapof_kmsid_to_token(_mongocrypt_tester_t *tester) { + mongocrypt_status_t *status = mongocrypt_status_new(); + bson_t *response1 = TMP_BSON(BSON_STR({"access_token" : "foo", "expires_in" : 1234})); + bson_t *response2 = TMP_BSON(BSON_STR({"access_token" : "bar", "expires_in" : 4567})); + + // Test inserting one entry. + { + mc_mapof_kmsid_to_token_t *k2t = mc_mapof_kmsid_to_token_new(); + ASSERT(NULL == mc_mapof_kmsid_to_token_get_token(k2t, "local:1")); + ASSERT_OK_STATUS(mc_mapof_kmsid_to_token_add_response(k2t, "local:1", response1, status), status); + char *got = mc_mapof_kmsid_to_token_get_token(k2t, "local:1"); + ASSERT_STREQUAL(got, "foo"); + bson_free(got); + mc_mapof_kmsid_to_token_destroy(k2t); + } + + // Test inserting two entries. + { + mc_mapof_kmsid_to_token_t *k2t = mc_mapof_kmsid_to_token_new(); + + // Insert first. + { + ASSERT(NULL == mc_mapof_kmsid_to_token_get_token(k2t, "local:1")); + ASSERT_OK_STATUS(mc_mapof_kmsid_to_token_add_response(k2t, "local:1", response1, status), status); + char *got = mc_mapof_kmsid_to_token_get_token(k2t, "local:1"); + ASSERT_STREQUAL(got, "foo"); + bson_free(got); + } + + // Insert second. + { + ASSERT(NULL == mc_mapof_kmsid_to_token_get_token(k2t, "local:2")); + ASSERT_OK_STATUS(mc_mapof_kmsid_to_token_add_response(k2t, "local:2", response2, status), status); + char *got = mc_mapof_kmsid_to_token_get_token(k2t, "local:2"); + ASSERT_STREQUAL(got, "bar"); + bson_free(got); + } + + mc_mapof_kmsid_to_token_destroy(k2t); + } + + // Test overwriting an entry. + { + mc_mapof_kmsid_to_token_t *k2t = mc_mapof_kmsid_to_token_new(); + + // Insert first. + { + ASSERT(NULL == mc_mapof_kmsid_to_token_get_token(k2t, "local:1")); + ASSERT_OK_STATUS(mc_mapof_kmsid_to_token_add_response(k2t, "local:1", response1, status), status); + char *got = mc_mapof_kmsid_to_token_get_token(k2t, "local:1"); + ASSERT_STREQUAL(got, "foo"); + bson_free(got); + } + + // Overwrite 'local:1' with a different token. + { + ASSERT_OK_STATUS(mc_mapof_kmsid_to_token_add_response(k2t, "local:1", response2, status), status); + char *got = mc_mapof_kmsid_to_token_get_token(k2t, "local:1"); + ASSERT_STREQUAL(got, "bar"); + bson_free(got); + } + + mc_mapof_kmsid_to_token_destroy(k2t); + } + // Test getting a missing entry. + { + mc_mapof_kmsid_to_token_t *k2t = mc_mapof_kmsid_to_token_new(); + ASSERT(NULL == mc_mapof_kmsid_to_token_get_token(k2t, "local:1")); + mc_mapof_kmsid_to_token_destroy(k2t); + } + mongocrypt_status_destroy(status); } void _mongocrypt_tester_install_cache_oauth(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_cache_oauth_expiration); -} \ No newline at end of file + INSTALL_TEST(test_mc_mapof_kmsid_to_token); +} diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cleanup.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cleanup.c new file mode 100644 index 0000000..43e7e0e --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cleanup.c @@ -0,0 +1,374 @@ +/* + * Copyright 2023-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" + +static void _test_cleanup_success(_mongocrypt_tester_t *tester) { + for (int use_range_v2 = 0; use_range_v2 <= 1; use_range_v2++) { + mongocrypt_t *crypt; + mongocrypt_ctx_t *ctx; + + crypt = + _mongocrypt_tester_mongocrypt(use_range_v2 ? TESTER_MONGOCRYPT_WITH_RANGE_V2 : TESTER_MONGOCRYPT_DEFAULT); + ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/cleanup/success/cmd.json")), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/cleanup/success/collinfo.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "ABCDEFAB123498761234123456789012-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789013-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + if (use_range_v2) { + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON( + TEST_FILE("./test/data/cleanup/success/encrypted-payload-range-v2.json"), + out); + } else { + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/cleanup/success/encrypted-payload.json"), + out); + } + mongocrypt_binary_destroy(out); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_DONE); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } +} + +static void _test_cleanup_nonlocal_kms(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt; + mongocrypt_ctx_t *ctx; + + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/cleanup/success/cmd.json")), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/cleanup/success/collinfo.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-aws-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "ABCDEFAB123498761234123456789012-aws-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789013-aws-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + { + mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kms_ctx); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789013-" + "aws-decrypt-reply.txt")), + kms_ctx); + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kms_ctx); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, + TEST_FILE("./test/data/keys/" + "ABCDEFAB123498761234123456789012-" + "aws-decrypt-reply.txt")), + kms_ctx); + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kms_ctx); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-" + "aws-decrypt-reply.txt")), + kms_ctx); + ASSERT(!mongocrypt_ctx_next_kms_ctx(ctx)); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/cleanup/success/encrypted-payload.json"), out); + mongocrypt_binary_destroy(out); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_DONE); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +static void _test_cleanup_missing_key_id(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt; + mongocrypt_ctx_t *ctx; + + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/cleanup/success/cmd.json")), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); + { + ASSERT_FAILS(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/cleanup/missing-key-id/collinfo.json")), + ctx, + "unable to find 'keyId' in 'field' document"); + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +static void _test_cleanup_key_not_provided(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt; + mongocrypt_ctx_t *ctx; + + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/cleanup/success/cmd.json")), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/cleanup/success/collinfo.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-local-document.json")), + ctx); + ASSERT_FAILS(mongocrypt_ctx_mongo_done(ctx), ctx, "not all keys requested were satisfied"); + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +static void _test_cleanup_need_kms_credentials(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt; + mongocrypt_ctx_t *ctx; + + crypt = mongocrypt_new(); + mongocrypt_setopt_use_need_kms_credentials_state(crypt); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {}}")), crypt); + mongocrypt_setopt_use_need_kms_credentials_state(crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/cleanup/success/cmd.json")), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/cleanup/success/collinfo.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS); + { + ASSERT_OK(mongocrypt_ctx_provide_kms_providers(ctx, + TEST_BSON("{'aws': {" + " 'accessKeyId': 'example'," + " 'secretAccessKey': 'example'}}")), + ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-aws-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "ABCDEFAB123498761234123456789012-aws-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789013-aws-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + { + mongocrypt_kms_ctx_t *kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kms_ctx); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789013-" + "aws-decrypt-reply.txt")), + kms_ctx); + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kms_ctx); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, + TEST_FILE("./test/data/keys/" + "ABCDEFAB123498761234123456789012-" + "aws-decrypt-reply.txt")), + kms_ctx); + kms_ctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kms_ctx); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-" + "aws-decrypt-reply.txt")), + kms_ctx); + ASSERT(!mongocrypt_ctx_next_kms_ctx(ctx)); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/cleanup/success/encrypted-payload.json"), out); + mongocrypt_binary_destroy(out); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_DONE); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +static void _test_cleanup_no_fields(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt; + mongocrypt_ctx_t *ctx; + + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/cleanup/success/cmd.json")), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/cleanup/no-fields/collinfo.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/cleanup/no-fields/encrypted-payload.json"), out); + mongocrypt_binary_destroy(out); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_DONE); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +static void _test_cleanup_from_encrypted_field_config_map(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt; + mongocrypt_ctx_t *ctx; + + /* Initialize crypt with encrypted_field_config_map */ + { + char localkey_data[MONGOCRYPT_KEY_LEN] = {0}; + mongocrypt_binary_t *localkey; + + crypt = mongocrypt_new(); + mongocrypt_setopt_log_handler(crypt, _mongocrypt_stdout_log_fn, NULL); + localkey = mongocrypt_binary_new_from_data((uint8_t *)localkey_data, sizeof localkey_data); + mongocrypt_setopt_kms_provider_local(crypt, localkey); + mongocrypt_binary_destroy(localkey); + ASSERT_OK(mongocrypt_setopt_encrypted_field_config_map( + crypt, + TEST_FILE("./test/data/cleanup/success/encrypted-field-config-map.json")), + crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + } + ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/cleanup/success/cmd.json")), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "ABCDEFAB123498761234123456789012-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789013-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/cleanup/success/encrypted-payload.json"), out); + mongocrypt_binary_destroy(out); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_DONE); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +void _mongocrypt_tester_install_cleanup(_mongocrypt_tester_t *tester) { + INSTALL_TEST(_test_cleanup_success); + INSTALL_TEST(_test_cleanup_nonlocal_kms); + INSTALL_TEST(_test_cleanup_missing_key_id); + INSTALL_TEST(_test_cleanup_key_not_provided); + INSTALL_TEST(_test_cleanup_need_kms_credentials); + INSTALL_TEST(_test_cleanup_no_fields); + INSTALL_TEST(_test_cleanup_from_encrypted_field_config_map); +} diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-compact.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-compact.c index 72d9764..255f709 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-compact.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-compact.c @@ -17,49 +17,128 @@ #include "test-mongocrypt.h" static void _test_compact_success(_mongocrypt_tester_t *tester) { - mongocrypt_t *crypt; - mongocrypt_ctx_t *ctx; - - crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); - ctx = mongocrypt_ctx_new(crypt); - - ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/compact/success/cmd.json")), ctx); - - ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); - { - ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/compact/success/collinfo.json")), ctx); - ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); - } - - ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); - { - ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, - TEST_FILE("./test/data/keys/" - "12345678123498761234123456789012-local-document.json")), - ctx); - ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, - TEST_FILE("./test/data/keys/" - "ABCDEFAB123498761234123456789012-local-document.json")), - ctx); - ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, - TEST_FILE("./test/data/keys/" - "12345678123498761234123456789013-local-document.json")), - ctx); - ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + const char basepath[] = "./test/data/compact/"; + char datapath[1000]; + char cmdfile[1000]; + char collfile[1000]; + char payloadfile[1000]; + strcpy(datapath, basepath); + size_t nullb = strlen(basepath); + for (int use_anchor_pad = 0; use_anchor_pad <= 1; use_anchor_pad++) { + for (int use_range_v2 = 0; use_range_v2 <= 1; use_range_v2++) { + datapath[nullb] = 0; + strcat(datapath, use_anchor_pad ? "anchor-pad/" : "success/"); + strcpy(cmdfile, datapath); + strcat(cmdfile, "cmd.json"); + strcpy(collfile, datapath); + strcat(collfile, "collinfo.json"); + strcpy(payloadfile, datapath); + strcat(payloadfile, use_range_v2 ? "encrypted-payload-range-v2.json" : "encrypted-payload.json"); + + mongocrypt_t *crypt; + mongocrypt_ctx_t *ctx; + + crypt = _mongocrypt_tester_mongocrypt(use_range_v2 ? TESTER_MONGOCRYPT_WITH_RANGE_V2 + : TESTER_MONGOCRYPT_DEFAULT); + ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE(cmdfile)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE(collfile)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "ABCDEFAB123498761234123456789012-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789013-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE(payloadfile), out); + mongocrypt_binary_destroy(out); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_DONE); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } } - ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); - { - mongocrypt_binary_t *out = mongocrypt_binary_new(); - ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); - ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/compact/success/encrypted-payload.json"), out); - mongocrypt_binary_destroy(out); + // Test `compactStructuredEncryptionData` without range fields omits encryptionInformation. + // This is a regression test for MONGOCRYPT-699. + for (int use_range_v2 = 0; use_range_v2 <= 1; use_range_v2++) { + datapath[nullb] = 0; + strcat(datapath, "no-range/"); + strcpy(cmdfile, datapath); + strcat(cmdfile, "cmd.json"); + strcpy(collfile, datapath); + strcat(collfile, "collinfo.json"); + strcpy(payloadfile, datapath); + strcat(payloadfile, "encrypted-payload.json"); // Expect same result regardless of range v2. + + mongocrypt_t *crypt; + mongocrypt_ctx_t *ctx; + + crypt = + _mongocrypt_tester_mongocrypt(use_range_v2 ? TESTER_MONGOCRYPT_WITH_RANGE_V2 : TESTER_MONGOCRYPT_DEFAULT); + ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE(cmdfile)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE(collfile)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "ABCDEFAB123498761234123456789012-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789013-local-document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE(payloadfile), out); + mongocrypt_binary_destroy(out); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_DONE); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); } - - ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_DONE); - - mongocrypt_ctx_destroy(ctx); - mongocrypt_destroy(crypt); } static void _test_compact_nonlocal_kms(_mongocrypt_tester_t *tester) { @@ -191,7 +270,7 @@ static void _test_compact_need_kms_credentials(_mongocrypt_tester_t *tester) { mongocrypt_setopt_use_need_kms_credentials_state(crypt); ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {}}")), crypt); mongocrypt_setopt_use_need_kms_credentials_state(crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/compact/success/cmd.json")), ctx); @@ -316,7 +395,7 @@ static void _test_compact_from_encrypted_field_config_map(_mongocrypt_tester_t * crypt, TEST_FILE("./test/data/compact/success/encrypted-field-config-map.json")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); } ctx = mongocrypt_ctx_new(crypt); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c index fb11f37..090d68e 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c @@ -17,6 +17,7 @@ #include "mongocrypt-config.h" #include "mongocrypt-crypto-private.h" #include "mongocrypt-private.h" +#include "test-mongocrypt-crypto-std-hooks.h" #include "test-mongocrypt.h" @@ -67,7 +68,8 @@ static bool _mock_aes_256_xxx_encrypt(void *ctx, } _append_bin("in", in); /* append it directly, don't encrypt. */ - memcpy(out->data + *bytes_written, in->data, in->len); + uint8_t *out_u8 = out->data; + memcpy(out_u8 + *bytes_written, in->data, in->len); *bytes_written += in->len; bson_string_append_printf(call_history, "ret:%s\n", BSON_FUNC); if (0 == strcmp((char *)ctx, "error_on:aes_256_cbc_encrypt") @@ -92,7 +94,8 @@ static bool _mock_aes_256_xxx_decrypt(void *ctx, _append_bin("iv", iv); _append_bin("in", in); /* append it directly, don't decrypt. */ - memcpy(out->data + *bytes_written, in->data, in->len); + uint8_t *out_u8 = out->data; + memcpy(out_u8 + *bytes_written, in->data, in->len); *bytes_written += in->len; bson_string_append_printf(call_history, "ret:%s\n", BSON_FUNC); if (0 == strcmp((char *)ctx, "error_on:aes_256_cbc_decrypt") @@ -245,7 +248,7 @@ _create_mongocrypt_and_hooks(_mongocrypt_tester_t *tester, const char *error_on, ret = mongocrypt_setopt_aes_256_ecb(crypt, _mock_aes_256_xxx_encrypt, (void *)error_on); ASSERT_OK(ret, crypt); } - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); return crypt; } @@ -550,7 +553,7 @@ static void _test_crypto_hooks_unset(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); mongocrypt_setopt_kms_provider_aws(crypt, "example", -1, "example", -1); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); mongocrypt_destroy(crypt); } @@ -757,6 +760,130 @@ void _test_fle2_crypto_via_ecb_hook(_mongocrypt_tester_t *tester) { } #endif +static void test_is_crypto_available_with_crypto_required(_mongocrypt_tester_t *tester) { + // libmongocrypt is built with native crypto. + ASSERT(mongocrypt_is_crypto_available()); +} + +static void test_is_crypto_available_with_crypto_prohibited(_mongocrypt_tester_t *tester) { + // libmongocrypt is not built with native crypto. + ASSERT(!mongocrypt_is_crypto_available()); +} + +static int ctr_encrypt_count; + +static bool _aes_256_ctr_encrypt_and_count(void *ctx, + mongocrypt_binary_t *key, + mongocrypt_binary_t *iv, + mongocrypt_binary_t *in, + mongocrypt_binary_t *out, + uint32_t *bytes_written, + mongocrypt_status_t *status) { + ctr_encrypt_count++; + return _std_hook_native_crypto_aes_256_ctr_encrypt(ctx, key, iv, in, out, bytes_written, status); +} + +static int ctr_decrypt_count; + +static bool _aes_256_ctr_decrypt_and_count(void *ctx, + mongocrypt_binary_t *key, + mongocrypt_binary_t *iv, + mongocrypt_binary_t *in, + mongocrypt_binary_t *out, + uint32_t *bytes_written, + mongocrypt_status_t *status) { + ctr_decrypt_count++; + return _std_hook_native_crypto_aes_256_ctr_decrypt(ctx, key, iv, in, out, bytes_written, status); +} + +static void test_setting_only_ctr_hook(_mongocrypt_tester_t *tester) { + // Test that the CTR hook can be set without setting other crypto hooks. + // This enables supporting macOS <= 10.14 in bindings using libmongocrypt with native crypto. + // macOS <= 10.14 does not support native CTR encryption. + + if (!_aes_ctr_is_supported_by_os) { + printf("Common Crypto with no CTR support detected. Skipping."); + return; + } + + // Configure KMS providers with local KEK used to encrypt key documents. + mongocrypt_binary_t *kms_providers = + TEST_BSON("{'local' : { 'key': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'}}"); + _mongocrypt_buffer_t key_id1, key_id2; + _mongocrypt_buffer_copy_from_hex(&key_id1, "12345678123498761234123456789012"); + _mongocrypt_buffer_copy_from_hex(&key_id2, "ABCDEFAB123498761234123456789012"); + + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK( + mongocrypt_setopt_aes_256_ctr(crypt, _aes_256_ctr_encrypt_and_count, _aes_256_ctr_decrypt_and_count, NULL), + crypt); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Encrypt with an algorithm using the CTR hook. + ctr_encrypt_count = 0; + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_id(ctx, _mongocrypt_buffer_as_binary(&key_id1)), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 1), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_INDEXED_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON("{'v' : 123}")), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "12345678123498761234123456789012-local-" + "document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *ciphertext = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, ciphertext), ctx); + mongocrypt_binary_destroy(ciphertext); + mongocrypt_ctx_destroy(ctx); + } + // CTR encrypt hook is called. + ASSERT_CMPINT(ctr_encrypt_count, ==, 1); + + // Decrypt with an algorithm using the CTR hook. + ctr_decrypt_count = 0; + { + // `ieev_payload_base64` is an IEEV payload, which uses the CTR hook to decrypt. + const char *ieev_payload_base64 = "BxI0VngSNJh2EjQSNFZ4kBICQ7uhTd9C2oI8M1afRon0ZaYG0s6oTmt0aBZ9kO4S4mm5vId01" + "BsW7tBHytA8pDJ2IiWBCmah3OGH2M4ET7PSqekQD4gkUCo4JeEttx4yj05Ou4D6yZUmYfVKmE" + "ljge16NCxKm7Ir9gvmQsp8x1wqGBzpndA6gkqFxsxfvQ/" + "cIqOwMW9dGTTWsfKge+jYkCUIFMfms+XyC/8evQhjjA+qR6eEmV+N/" + "kwpR7Q7TJe0lwU5kw2kSe3/KiPKRZZTbn8znadvycfJ0cCWGad9SQ=="; + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init( + ctx, + TEST_BSON("{'v':{'$binary':{'base64': '%s','subType':'6'}}}", ieev_payload_base64)), + ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, + TEST_FILE("./test/data/keys/" + "ABCDEFAB123498761234123456789012-local-" + "document.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *decrypted = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, decrypted), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(decrypted, TEST_BSON("{'v': 'value123'}")); + mongocrypt_binary_destroy(decrypted); + mongocrypt_ctx_destroy(ctx); + } + // CTR decrypt hook is called repeatedly. + ASSERT_CMPINT(ctr_decrypt_count, ==, 4); + + _mongocrypt_buffer_cleanup(&key_id2); + _mongocrypt_buffer_cleanup(&key_id1); + mongocrypt_destroy(crypt); +} + void _mongocrypt_tester_install_crypto_hooks(_mongocrypt_tester_t *tester) { INSTALL_TEST_CRYPTO(_test_crypto_hooks_encryption, CRYPTO_OPTIONAL); INSTALL_TEST_CRYPTO(_test_crypto_hooks_decryption, CRYPTO_OPTIONAL); @@ -767,6 +894,9 @@ void _mongocrypt_tester_install_crypto_hooks(_mongocrypt_tester_t *tester) { INSTALL_TEST_CRYPTO(_test_crypto_hooks_explicit_err, CRYPTO_OPTIONAL); INSTALL_TEST_CRYPTO(_test_crypto_hooks_explicit_sha256_err, CRYPTO_OPTIONAL); INSTALL_TEST_CRYPTO(_test_crypto_hook_sign_rsaes_pkcs1_v1_5, CRYPTO_OPTIONAL); + INSTALL_TEST_CRYPTO(test_is_crypto_available_with_crypto_required, CRYPTO_REQUIRED); + INSTALL_TEST_CRYPTO(test_is_crypto_available_with_crypto_prohibited, CRYPTO_PROHIBITED); + INSTALL_TEST_CRYPTO(test_setting_only_ctr_hook, CRYPTO_REQUIRED); #ifdef MONGOCRYPT_ENABLE_CRYPTO_LIBCRYPTO INSTALL_TEST(_test_fle2_crypto_via_ecb_hook); #endif diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.c index 4d6c295..85c569c 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.c @@ -54,6 +54,46 @@ bool _std_hook_native_crypto_aes_256_cbc_decrypt(void *ctx, return _native_crypto_aes_256_cbc_decrypt(args); } +bool _std_hook_native_crypto_aes_256_ctr_encrypt(void *ctx, + mongocrypt_binary_t *key, + mongocrypt_binary_t *iv, + mongocrypt_binary_t *in, + mongocrypt_binary_t *out, + uint32_t *bytes_written, + mongocrypt_status_t *status) { + _mongocrypt_buffer_t key_buf; + _mongocrypt_buffer_from_binary(&key_buf, key); + _mongocrypt_buffer_t iv_buf; + _mongocrypt_buffer_from_binary(&iv_buf, iv); + _mongocrypt_buffer_t in_buf; + _mongocrypt_buffer_from_binary(&in_buf, in); + _mongocrypt_buffer_t out_buf; + _mongocrypt_buffer_from_binary(&out_buf, out); + + aes_256_args_t args = {&key_buf, &iv_buf, &in_buf, &out_buf, bytes_written, status}; + return _native_crypto_aes_256_ctr_encrypt(args); +} + +bool _std_hook_native_crypto_aes_256_ctr_decrypt(void *ctx, + mongocrypt_binary_t *key, + mongocrypt_binary_t *iv, + mongocrypt_binary_t *in, + mongocrypt_binary_t *out, + uint32_t *bytes_written, + mongocrypt_status_t *status) { + _mongocrypt_buffer_t key_buf; + _mongocrypt_buffer_from_binary(&key_buf, key); + _mongocrypt_buffer_t iv_buf; + _mongocrypt_buffer_from_binary(&iv_buf, iv); + _mongocrypt_buffer_t in_buf; + _mongocrypt_buffer_from_binary(&in_buf, in); + _mongocrypt_buffer_t out_buf; + _mongocrypt_buffer_from_binary(&out_buf, out); + + aes_256_args_t args = {&key_buf, &iv_buf, &in_buf, &out_buf, bytes_written, status}; + return _native_crypto_aes_256_ctr_decrypt(args); +} + bool _std_hook_native_crypto_random(void *ctx, mongocrypt_binary_t *out, uint32_t count, mongocrypt_status_t *status) { _mongocrypt_buffer_t outbuf; _mongocrypt_buffer_from_binary(&outbuf, out); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.h b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.h index b73e2fd..7df41a5 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.h +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.h @@ -40,6 +40,22 @@ bool _std_hook_native_crypto_aes_256_cbc_decrypt(void *ctx, uint32_t *bytes_written, mongocrypt_status_t *status); +bool _std_hook_native_crypto_aes_256_ctr_encrypt(void *ctx, + mongocrypt_binary_t *key, + mongocrypt_binary_t *iv, + mongocrypt_binary_t *in, + mongocrypt_binary_t *out, + uint32_t *bytes_written, + mongocrypt_status_t *status); + +bool _std_hook_native_crypto_aes_256_ctr_decrypt(void *ctx, + mongocrypt_binary_t *key, + mongocrypt_binary_t *iv, + mongocrypt_binary_t *in, + mongocrypt_binary_t *out, + uint32_t *bytes_written, + mongocrypt_status_t *status); + bool _std_hook_native_crypto_random(void *ctx, mongocrypt_binary_t *out, uint32_t count, mongocrypt_status_t *status); bool _std_hook_native_hmac_sha512(void *ctx, diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-csfle-lib.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-csfle-lib.c index 217166b..89eca16 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-csfle-lib.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-csfle-lib.c @@ -15,7 +15,7 @@ static mongocrypt_t *get_test_mongocrypt(_mongocrypt_tester_t *tester) { static void _test_csfle_no_paths(_mongocrypt_tester_t *tester) { /// Test that mongocrypt_init succeeds if we have no search path mongocrypt_t *const crypt = get_test_mongocrypt(tester); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); // No csfle was loaded: BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt, NULL) == NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt) == 0); @@ -27,7 +27,7 @@ static void _test_csfle_not_found(_mongocrypt_tester_t *tester) { /// found but a search path was specified mongocrypt_t *const crypt = get_test_mongocrypt(tester); mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt, "/no-such-directory"); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); // No csfle was loaded: BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt, NULL) == NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt) == 0); @@ -39,7 +39,7 @@ static void _test_csfle_load(_mongocrypt_tester_t *tester) { mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt, "no-such-directory"); mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt, "$ORIGIN"); mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt, "another-no-such-dir"); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); // csfle WAS loaded: BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt, NULL) != NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt) != 0); @@ -55,14 +55,14 @@ static void _test_csfle_load(_mongocrypt_tester_t *tester) { static void _test_csfle_load_twice(_mongocrypt_tester_t *tester) { mongocrypt_t *const crypt1 = get_test_mongocrypt(tester); mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt1, "$ORIGIN"); - ASSERT_OK(mongocrypt_init(crypt1), crypt1); + ASSERT_OK(_mongocrypt_init_for_test(crypt1), crypt1); BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt1, NULL) != NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt1) != 0); // Make another one: mongocrypt_t *const crypt2 = get_test_mongocrypt(tester); mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt2, "$ORIGIN"); - ASSERT_OK(mongocrypt_init(crypt2), crypt2); + ASSERT_OK(_mongocrypt_init_for_test(crypt2), crypt2); // csfle was loaded again: BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt2, NULL) != NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt2) != 0); @@ -88,7 +88,7 @@ static void _test_csfle_load_twice(_mongocrypt_tester_t *tester) { static void _test_csfle_load_twice_fail(_mongocrypt_tester_t *tester) { mongocrypt_t *const crypt1 = get_test_mongocrypt(tester); mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt1, "$ORIGIN"); - ASSERT_OK(mongocrypt_init(crypt1), crypt1); + ASSERT_OK(_mongocrypt_init_for_test(crypt1), crypt1); BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt1, NULL) != NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt1) != 0); @@ -96,7 +96,7 @@ static void _test_csfle_load_twice_fail(_mongocrypt_tester_t *tester) { mongocrypt_t *const crypt2 = get_test_mongocrypt(tester); mongocrypt_setopt_set_crypt_shared_lib_path_override(crypt2, "$ORIGIN/stubbed-crypt_shared-2.dll"); // Loading a second different library is an error: - ASSERT_FAILS(mongocrypt_init(crypt2), crypt2, "attempted to load a second CSFLE library"); + ASSERT_FAILS(_mongocrypt_init_for_test(crypt2), crypt2, "attempted to load a second CSFLE library"); mstr_view version = mstrv_view_cstr(mongocrypt_crypt_shared_lib_version_string(crypt1, NULL)); if (TEST_MONGOCRYPT_HAVE_REAL_CRYPT_SHARED_LIB) { @@ -113,7 +113,7 @@ static void _test_csfle_path_override_okay(_mongocrypt_tester_t *tester) { mongocrypt_t *const crypt = get_test_mongocrypt(tester); // Set to the absolute path to the DLL we use for testing: mongocrypt_setopt_set_crypt_shared_lib_path_override(crypt, "$ORIGIN/mongo_crypt_v1" MCR_DLL_SUFFIX); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); // csfle WAS loaded: BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt, NULL) != NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt) != 0); @@ -134,7 +134,7 @@ static void _test_csfle_path_override_fail(_mongocrypt_tester_t *tester) { // This *would* succeed, but we don't use the search paths if an absolute // override was specified: mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt, "$ORIGIN"); - ASSERT_FAILS(mongocrypt_init(crypt), crypt, "but we failed to open a dynamic library at that location"); + ASSERT_FAILS(_mongocrypt_init_for_test(crypt), crypt, "but we failed to open a dynamic library at that location"); BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt, NULL) == NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt) == 0); mongocrypt_destroy(crypt); @@ -151,7 +151,7 @@ static void _test_csfle_not_loaded_with_bypassqueryanalysis(_mongocrypt_tester_t mongocrypt_t *const crypt = get_test_mongocrypt(tester); mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt, "$ORIGIN"); mongocrypt_setopt_bypass_query_analysis(crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt, NULL) == NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt) == 0); @@ -164,7 +164,7 @@ static void _test_override_error_includes_reason(_mongocrypt_tester_t *tester) { mongocrypt_t *crypt = get_test_mongocrypt(tester); // Set an incorrect override path. mongocrypt_setopt_set_crypt_shared_lib_path_override(crypt, "invalid_path_to_crypt_shared.so"); - ASSERT_FAILS(mongocrypt_init(crypt), crypt, "Error while opening candidate"); + ASSERT_FAILS(_mongocrypt_init_for_test(crypt), crypt, "Error while opening candidate"); BSON_ASSERT(mongocrypt_crypt_shared_lib_version_string(crypt, NULL) == NULL); BSON_ASSERT(mongocrypt_crypt_shared_lib_version(crypt) == 0); mongocrypt_destroy(crypt); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-decrypt.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-decrypt.c index 33e7e82..67c8639 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-decrypt.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-decrypt.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "kms_message/kms_b64.h" // kms_message_raw_to_b64 #include "mongocrypt-ctx-private.h" #include "mongocrypt.h" #include "test-mongocrypt-assert-match-bson.h" @@ -128,7 +129,7 @@ void _test_decrypt_empty_aws(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); ASSERT_OK(mongocrypt_setopt_kms_provider_aws(crypt, "", -1, "", -1), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_decrypt_init(ctx, TEST_FILE("./test/data/encrypted-cmd.json")), ctx); @@ -183,7 +184,7 @@ static void _test_decrypt_per_ctx_credentials(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); mongocrypt_setopt_use_need_kms_credentials_state(crypt); mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {}}")); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); /* Encrypt an empty binary value. */ @@ -220,8 +221,9 @@ static void _test_decrypt_per_ctx_credentials_local(_mongocrypt_tester_t *tester _mongocrypt_buffer_t encrypted; /* local_kek is the KEK used to encrypt the keyMaterial in * ./test/data/key-document-local.json */ - const char *local_kek = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + uint8_t local_kek_raw[MONGOCRYPT_KEY_LEN] = {0}; + char *local_kek = kms_message_raw_to_b64(local_kek_raw, sizeof(local_kek_raw)); + /* local_uuid is the hex of the UUID of the key in * ./test/data/key-document-local.json */ const char *local_uuid = "61616161616161616161616161616161"; @@ -231,7 +233,7 @@ static void _test_decrypt_per_ctx_credentials_local(_mongocrypt_tester_t *tester crypt = mongocrypt_new(); mongocrypt_setopt_use_need_kms_credentials_state(crypt); mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'local': {}}")); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); /* Encrypt an empty binary value. */ @@ -265,6 +267,7 @@ static void _test_decrypt_per_ctx_credentials_local(_mongocrypt_tester_t *tester mongocrypt_ctx_destroy(ctx); _mongocrypt_buffer_cleanup(&encrypted); mongocrypt_destroy(crypt); + bson_free(local_kek); } static void _test_decrypt_fle2(_mongocrypt_tester_t *tester) { diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c index 9dc2895..e362846 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c @@ -16,6 +16,8 @@ #include +#include "kms_message/kms_b64.h" +#include "mongocrypt-crypto-private.h" // MONGOCRYPT_KEY_LEN #include "test-mongocrypt-assert-match-bson.h" #include "test-mongocrypt-crypto-std-hooks.h" #include "test-mongocrypt.h" @@ -350,9 +352,7 @@ static void _test_encrypt_init(_mongocrypt_tester_t *tester) { /* Empty coll name is an error. */ ctx = mongocrypt_ctx_new(crypt); - ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "", -1, TEST_BSON("{'find': ''}")), - ctx, - "empty collection name on command"); + ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "", -1, TEST_BSON("{'find': ''}")), ctx, "invalid db"); mongocrypt_ctx_destroy(ctx); mongocrypt_destroy(crypt); @@ -660,7 +660,7 @@ static void _test_local_schema(_mongocrypt_tester_t *tester) { schema_map = TEST_FILE("./test/data/schema-map.json"); ASSERT_OK(mongocrypt_setopt_kms_provider_aws(crypt, "example", -1, "example", -1), crypt); ASSERT_OK(mongocrypt_setopt_schema_map(crypt, schema_map), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); /* Schema map has test.test, we should jump right to NEED_MONGO_MARKINGS */ ctx = mongocrypt_ctx_new(crypt); @@ -837,7 +837,7 @@ static void _test_encrypt_is_remote_schema(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); ASSERT_OK(mongocrypt_setopt_kms_provider_aws(crypt, "example", -1, "example", -1), crypt); ASSERT_OK(mongocrypt_setopt_schema_map(crypt, TEST_FILE("./test/data/schema-map.json")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); @@ -953,12 +953,17 @@ static void _test_encrypt_init_each_cmd(_mongocrypt_tester_t *tester) { _init_bypass(tester, "{'killSessions': 1}"); _init_bypass(tester, "{'killAllSessionsByPattern': 1}"); _init_bypass(tester, "{'refreshSessions': 1}"); + _init_ok(tester, "{'cleanupStructuredEncryptionData': 'coll'}"); _init_ok(tester, "{'compactStructuredEncryptionData': 'coll'}"); _init_bypass(tester, "{'hello': 1}"); _init_bypass(tester, "{'buildInfo': 1}"); _init_bypass(tester, "{'getCmdLineOpts': 1}"); _init_bypass(tester, "{'getLog': 1}"); _init_ok(tester, "{'collMod': 'coll'}"); + _init_bypass(tester, "{'listSearchIndexes': 'coll' }"); + _init_bypass(tester, "{'createSearchIndexes': 'coll' }"); + _init_bypass(tester, "{'dropSearchIndex': 'coll' }"); + _init_bypass(tester, "{'updateSearchIndex': 'coll' }"); } static void _test_encrypt_invalid_siblings(_mongocrypt_tester_t *tester) { @@ -1082,7 +1087,7 @@ void _test_encrypt_empty_aws(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); ASSERT_OK(mongocrypt_setopt_kms_provider_aws(crypt, "", -1, "", -1), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/example/cmd.json")), ctx); @@ -1134,7 +1139,7 @@ static void _test_encrypt_per_ctx_credentials(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); mongocrypt_setopt_use_need_kms_credentials_state(crypt); mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {}}")); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS); @@ -1167,7 +1172,7 @@ static void _test_encrypt_per_ctx_credentials_given_empty(_mongocrypt_tester_t * crypt = mongocrypt_new(); mongocrypt_setopt_use_need_kms_credentials_state(crypt); mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {}}")); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS); @@ -1183,13 +1188,13 @@ static void _test_encrypt_per_ctx_credentials_local(_mongocrypt_tester_t *tester mongocrypt_ctx_t *ctx; /* local_kek is the KEK used to encrypt the keyMaterial in * ./test/data/key-document-local.json */ - const char *local_kek = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + uint8_t local_kek_raw[MONGOCRYPT_KEY_LEN] = {0}; + char *local_kek = kms_message_raw_to_b64(local_kek_raw, sizeof(local_kek_raw)); crypt = mongocrypt_new(); mongocrypt_setopt_use_need_kms_credentials_state(crypt); mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'local': {}}")); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); _mongocrypt_tester_run_ctx_to(tester, ctx, MONGOCRYPT_CTX_NEED_KMS_CREDENTIALS); @@ -1204,6 +1209,7 @@ static void _test_encrypt_per_ctx_credentials_local(_mongocrypt_tester_t *tester mongocrypt_ctx_destroy(ctx); mongocrypt_destroy(crypt); + bson_free(local_kek); } static void _test_encrypt_with_aws_session_token(_mongocrypt_tester_t *tester) { @@ -1219,7 +1225,7 @@ static void _test_encrypt_with_aws_session_token(_mongocrypt_tester_t *tester) { "'accessKeyId': 'myAccessKeyId', " "'secretAccessKey': 'mySecretAccessKey'}}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); @@ -1299,7 +1305,7 @@ static void _test_encrypt_with_encrypted_field_config_map(_mongocrypt_tester_t * // TODO(MONGOCRYPT-572): This test uses the QEv1 protocol. Update this test for QEv2 or remove. Note: decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, false), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); /* Test encrypting a command on a collection present in the encrypted field * config map. */ @@ -1345,7 +1351,7 @@ static void _test_encrypt_with_encrypted_field_config_map_bypassed(_mongocrypt_t mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'bar'}}")), crypt); ASSERT_OK(mongocrypt_setopt_encrypted_field_config_map(crypt, TEST_BSON("{'db.coll': {'fields': []}}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); /* 'drop' is bypassed. Expect that no 'encryptionInformation' is appended. */ @@ -1409,7 +1415,7 @@ static void _test_encrypt_remote_encryptedfields(_mongocrypt_tester_t *tester) { // TODO(MONGOCRYPT-572): This test uses the QEv1 protocol. Update this test for QEv2 or remove. Note: decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, false), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); /* Test success. */ { ctx = mongocrypt_ctx_new(crypt); @@ -1474,7 +1480,7 @@ static void _test_encrypt_remote_encryptedfields(_mongocrypt_tester_t *tester) { // TODO(MONGOCRYPT-572): This test uses the QEv1 protocol. Update this test for QEv2 or remove. Note: decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, false), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/fle2-find-explicit/cmd.json")), ctx); @@ -1524,7 +1530,7 @@ static void _test_encrypt_with_bypassqueryanalysis(_mongocrypt_tester_t *tester) // TODO(MONGOCRYPT-572): This test uses the QEv1 protocol. Update this test for QEv2 or remove. Note: decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, false), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/fle2-find-explicit/cmd.json")), @@ -1556,7 +1562,7 @@ static void _test_encrypt_with_bypassqueryanalysis(_mongocrypt_tester_t *tester) // TODO(MONGOCRYPT-572): This test uses the QEv1 protocol. Update this test for QEv2 or remove. Note: decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, false), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/fle2-find-explicit/cmd.json")), @@ -1614,7 +1620,7 @@ static void _test_FLE2EncryptionPlaceholder_parse(_mongocrypt_tester_t *tester) ASSERT_CMPBUF(placeholder.user_key_id, expect_user_key_id); _mongocrypt_buffer_cleanup(&expect_user_key_id); - ASSERT(placeholder.maxContentionCounter == 0); + ASSERT(placeholder.maxContentionFactor == 0); mc_FLE2EncryptionPlaceholder_cleanup(&placeholder); _mongocrypt_buffer_cleanup(&buf); @@ -1658,7 +1664,8 @@ static void _test_FLE2EncryptionPlaceholder_range_parse(_mongocrypt_tester_t *te { mc_FLE2RangeInsertSpec_t spec; - ASSERT_OK_STATUS(mc_FLE2RangeInsertSpec_parse(&spec, &placeholder.v_iter, status), status); + ASSERT_OK_STATUS(mc_FLE2RangeInsertSpec_parse(&spec, &placeholder.v_iter, false /* use_range_v2 */, status), + status); ASSERT(BSON_ITER_HOLDS_INT32(&spec.v)); ASSERT_CMPINT32(bson_iter_int32(&spec.v), ==, 123456); @@ -1714,7 +1721,8 @@ static void _test_FLE2EncryptionPlaceholder_range_parse(_mongocrypt_tester_t *te { mc_FLE2RangeFindSpec_t spec; - ASSERT_OK_STATUS(mc_FLE2RangeFindSpec_parse(&spec, &placeholder.v_iter, status), status); + ASSERT_OK_STATUS(mc_FLE2RangeFindSpec_parse(&spec, &placeholder.v_iter, false /* use_range_v2 */, status), + status); ASSERT(spec.edgesInfo.set); @@ -1785,7 +1793,8 @@ static void _test_FLE2EncryptionPlaceholder_range_parse(_mongocrypt_tester_t *te { mc_FLE2RangeFindSpec_t spec; - ASSERT_OK_STATUS(mc_FLE2RangeFindSpec_parse(&spec, &placeholder.v_iter, status), status); + ASSERT_OK_STATUS(mc_FLE2RangeFindSpec_parse(&spec, &placeholder.v_iter, false /* use_range_v2 */, status), + status); ASSERT(spec.edgesInfo.set); @@ -1854,7 +1863,8 @@ static void _test_FLE2EncryptionPlaceholder_range_parse(_mongocrypt_tester_t *te { mc_FLE2RangeInsertSpec_t spec; - ASSERT_OK_STATUS(mc_FLE2RangeInsertSpec_parse(&spec, &placeholder.v_iter, status), status); + ASSERT_OK_STATUS(mc_FLE2RangeInsertSpec_parse(&spec, &placeholder.v_iter, false /* use_range_v2 */, status), + status); ASSERT(BSON_ITER_HOLDS_DOUBLE(&spec.v)); ASSERT_CMPDOUBLE(bson_iter_double(&spec.v), ==, 123.456); @@ -1922,7 +1932,11 @@ static void _test_encrypt_fle2_encryption_placeholder(_mongocrypt_tester_t *test char pathbuf[2048]; #define MAKE_PATH(mypath) \ - ASSERT(snprintf(pathbuf, sizeof(pathbuf), "./test/data/%s/%s", data_path, mypath) < sizeof(pathbuf)) + if (1) { \ + int pathbuf_ret = snprintf(pathbuf, sizeof(pathbuf), "./test/data/%s/%s", data_path, mypath); \ + ASSERT(pathbuf_ret >= 0 && (size_t)pathbuf_ret < sizeof(pathbuf)); \ + } else \ + ((void)0) if (!_aes_ctr_is_supported_by_os) { printf("Common Crypto with no CTR support detected. Skipping."); @@ -1956,7 +1970,7 @@ static void _test_encrypt_fle2_encryption_placeholder(_mongocrypt_tester_t *test MAKE_PATH("encrypted-field-map.json"); ASSERT_OK(mongocrypt_setopt_encrypted_field_config_map(crypt, TEST_FILE(pathbuf)), crypt); mongocrypt_binary_destroy(localkey); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); } /* Create encryption context. */ @@ -2155,7 +2169,7 @@ static void _test_encrypt_fle2_find_range_payload_decimal128_precision(_mongocry } #endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT -static mongocrypt_t *_crypt_with_rng(_test_rng_data_source *rng_source, bool use_v2) { +static mongocrypt_t *_crypt_with_rng(_test_rng_data_source *rng_source, bool use_v2, bool use_range_v2) { mongocrypt_t *crypt; mongocrypt_binary_t *localkey; /* localkey_data is the KEK used to encrypt the keyMaterial @@ -2180,7 +2194,12 @@ static mongocrypt_t *_crypt_with_rng(_test_rng_data_source *rng_source, bool use // TODO(MONGOCRYPT-572): This test uses the QEv1 protocol. Update this test for QEv2 or remove. Note: decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, use_v2), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + if (use_range_v2) { + ASSERT_OK(mongocrypt_setopt_use_range_v2(crypt), crypt); + ASSERT_OK(mongocrypt_init(crypt), crypt); + } else { + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + } return crypt; } @@ -2200,6 +2219,7 @@ typedef struct { const char *expect_init_error; bool is_expression; bool use_v2; + bool use_range_v2; } ee_testcase; static void ee_testcase_run(ee_testcase *tc) { @@ -2210,13 +2230,16 @@ static void ee_testcase_run(ee_testcase *tc) { if (tc->rng_data.buf.len > 0) { // Use fixed data for random number generation to produce deterministic // results. - crypt = _crypt_with_rng(&tc->rng_data, tc->use_v2); + crypt = _crypt_with_rng(&tc->rng_data, tc->use_v2, tc->use_range_v2); } else { tester_mongocrypt_flags flags = TESTER_MONGOCRYPT_DEFAULT; // TODO(MONGOCRYPT-572): Remove tests cases for QEv1. if (!tc->use_v2) { flags |= TESTER_MONGOCRYPT_WITH_CRYPT_V1; } + if (tc->use_range_v2) { + flags |= TESTER_MONGOCRYPT_WITH_RANGE_V2; + } crypt = _mongocrypt_tester_mongocrypt(flags); } mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -2446,17 +2469,10 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { * Second 16 bytes are IV for 'p' field in FLE2InsertUpdatePayload * Third 16 bytes are IV for 'v' field in FLE2InsertUpdatePayload */ -#ifdef MONGOCRYPT_LITTLE_ENDIAN #define RNG_DATA \ "\x01\x00\x00\x00\x00\x00\x00\x00" \ "\xc7\x43\xd6\x75\x76\x9e\xa7\x88\xd5\xe5\xc4\x40\xdb\x24\x0d\xf9" \ "\x4c\xd9\x64\x10\x43\x81\xe6\x61\xfa\x1f\xa0\x5c\x49\x8e\xad\x21" -#else -#define RNG_DATA \ - "\x00\x00\x00\x00\x00\x00\x00\x01" \ - "\xc7\x43\xd6\x75\x76\x9e\xa7\x88\xd5\xe5\xc4\x40\xdb\x24\x0d\xf9" \ - "\x4c\xd9\x64\x10\x43\x81\xe6\x61\xfa\x1f\xa0\x5c\x49\x8e\xad\x21" -#endif /* MONGOCRYPT_LITTLE_ENDIAN */ uint8_t rng_data[] = RNG_DATA; tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data, .len = sizeof(rng_data) - 1u}}; #undef RNG_DATA @@ -2479,17 +2495,10 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { * Second 16 bytes are IV for 'p' field in FLE2InsertUpdatePayload * Third 16 bytes are IV for 'v' field in FLE2InsertUpdatePayload */ -#ifdef MONGOCRYPT_LITTLE_ENDIAN #define RNG_DATA \ "\x01\x00\x00\x00\x00\x00\x00\x00" \ "\xc7\x43\xd6\x75\x76\x9e\xa7\x88\xd5\xe5\xc4\x40\xdb\x24\x0d\xf9" \ "\x4c\xd9\x64\x10\x43\x81\xe6\x61\xfa\x1f\xa0\x5c\x49\x8e\xad\x21" -#else -#define RNG_DATA \ - "\x00\x00\x00\x00\x00\x00\x00\x01" \ - "\xc7\x43\xd6\x75\x76\x9e\xa7\x88\xd5\xe5\xc4\x40\xdb\x24\x0d\xf9" \ - "\x4c\xd9\x64\x10\x43\x81\xe6\x61\xfa\x1f\xa0\x5c\x49\x8e\xad\x21" -#endif /* MONGOCRYPT_LITTLE_ENDIAN */ uint8_t rng_data[] = RNG_DATA; tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data, .len = sizeof(rng_data) - 1u}}; #undef RNG_DATA @@ -2659,7 +2668,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { #include "./data/fle2-insert-range-explicit/int32/RNG_DATA.h" tc.rng_data = (_test_rng_data_source){.buf = {.data = (uint8_t *)RNG_DATA, .len = sizeof(RNG_DATA) - 1}}; #undef RNG_DATA - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); @@ -2680,7 +2689,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { #include "./data/fle2-insert-range-explicit/int32/RNG_DATA.h" tc.rng_data = (_test_rng_data_source){.buf = {.data = (uint8_t *)RNG_DATA, .len = sizeof(RNG_DATA) - 1}}; #undef RNG_DATA - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); @@ -2702,7 +2711,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { #include "./data/fle2-insert-range-explicit/sparsity-2/RNG_DATA.h" tc.rng_data = (_test_rng_data_source){.buf = {.data = (uint8_t *)RNG_DATA, .len = sizeof(RNG_DATA) - 1}}; #undef RNG_DATA - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); @@ -2723,7 +2732,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { #include "./data/fle2-insert-range-explicit/sparsity-2/RNG_DATA.h" tc.rng_data = (_test_rng_data_source){.buf = {.data = (uint8_t *)RNG_DATA, .len = sizeof(RNG_DATA) - 1}}; #undef RNG_DATA - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); @@ -2742,11 +2751,11 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "algorithm='Range' with query_type='range' with int32"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &keyABC_id; tc.contention_factor = OPT_I64(4); - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.range_opts = TEST_FILE("./test/data/fle2-find-range-explicit/" "int32/rangeopts.json"); tc.msg = TEST_FILE("./test/data/fle2-find-range-explicit/int32/" @@ -2761,11 +2770,11 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "algorithm='Range' with query_type='range' with int32 (v2)"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &keyABC_id; tc.contention_factor = OPT_I64(4); - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.range_opts = TEST_FILE("./test/data/fle2-find-range-explicit/" "int32/rangeopts.json"); tc.msg = TEST_FILE("./test/data/fle2-find-range-explicit/int32/" @@ -2781,7 +2790,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "An unsupported range BSON type is an error"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON("{'min': 0, 'max': 1, 'sparsity': {'$numberLong': '1'}}"); @@ -2794,7 +2803,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "An unsupported range BSON type is an error (v2)"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON("{'min': 0, 'max': 1, 'sparsity': {'$numberLong': '1'}}"); @@ -2809,11 +2818,11 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { ee_testcase tc = {0}; tc.desc = "algorithm='Range' with query_type='range' with double with " "precision"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.range_opts = TEST_FILE("./test/data/fle2-find-range-explicit/double-precision/" "rangeopts.json"); tc.msg = TEST_FILE("./test/data/fle2-find-range-explicit/" @@ -2830,11 +2839,11 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { ee_testcase tc = {0}; tc.desc = "algorithm='Range' with query_type='range' with double with " "precision (v2)"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.range_opts = TEST_FILE("./test/data/fle2-find-range-explicit/double-precision/" "rangeopts.json"); tc.msg = TEST_FILE("./test/data/fle2-find-range-explicit/" @@ -2854,7 +2863,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { #include "./data/fle2-insert-range-explicit/double-precision/RNG_DATA.h" tc.rng_data = (_test_rng_data_source){.buf = {.data = (uint8_t *)RNG_DATA, .len = sizeof(RNG_DATA) - 1}}; #undef RNG_DATA - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); @@ -2875,7 +2884,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { #include "./data/fle2-insert-range-explicit/double-precision/RNG_DATA.h" tc.rng_data = (_test_rng_data_source){.buf = {.data = (uint8_t *)RNG_DATA, .len = sizeof(RNG_DATA) - 1}}; #undef RNG_DATA - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); @@ -2895,11 +2904,11 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { ee_testcase tc = {0}; tc.desc = "algorithm='Range' with query_type='range' with double without " "precision"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.range_opts = TEST_FILE("./test/data/fle2-find-range-explicit/double/" "rangeopts.json"); tc.msg = TEST_FILE("./test/data/fle2-find-range-explicit/double/value-to-encrypt.json"); @@ -2914,11 +2923,11 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { ee_testcase tc = {0}; tc.desc = "algorithm='Range' with query_type='range' with double without " "precision (v2)"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.range_opts = TEST_FILE("./test/data/fle2-find-range-explicit/double/" "rangeopts.json"); tc.msg = TEST_FILE("./test/data/fle2-find-range-explicit/double/value-to-encrypt.json"); @@ -2936,7 +2945,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { #include "./data/fle2-insert-range-explicit/double/RNG_DATA.h" tc.rng_data = (_test_rng_data_source){.buf = {.data = (uint8_t *)RNG_DATA, .len = sizeof(RNG_DATA) - 1}}; #undef RNG_DATA - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); @@ -2956,7 +2965,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { #include "./data/fle2-insert-range-explicit/double/RNG_DATA.h" tc.rng_data = (_test_rng_data_source){.buf = {.data = (uint8_t *)RNG_DATA, .len = sizeof(RNG_DATA) - 1}}; #undef RNG_DATA - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.index_key_id = &key123_id; tc.contention_factor = OPT_I64(0); @@ -2974,7 +2983,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "min > max for insert"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON("{'min': 1, 'max': 0, 'sparsity': {'$numberLong': '1'}}"); @@ -2987,7 +2996,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "min > max for insert (v2)"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON("{'min': 1, 'max': 0, 'sparsity': {'$numberLong': '1'}}"); @@ -3001,8 +3010,8 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "min > max for find"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON("{'min': 25, 'max': 24, 'sparsity': {'$numberLong': '1'}}"); @@ -3016,8 +3025,8 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "min > max for find (v2)"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON("{'min': 25, 'max': 24, 'sparsity': {'$numberLong': '1'}}"); @@ -3031,8 +3040,8 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "open interval"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_FILE("./test/data/fle2-find-range-explicit/" @@ -3049,8 +3058,8 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "open interval (v2)"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_FILE("./test/data/fle2-find-range-explicit/" @@ -3070,7 +3079,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "min is required to insert int for range"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON(RAW_STRING({"max" : {"$numberInt" : "200"}, "sparsity" : {"$numberLong" : "1"}})); @@ -3083,7 +3092,7 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "max is required to insert int for range"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON(RAW_STRING({"min" : {"$numberInt" : "0"}, "sparsity" : {"$numberLong" : "1"}})); @@ -3096,8 +3105,8 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "min is required to find int for range"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON(RAW_STRING({"max" : {"$numberInt" : "200"}, "sparsity" : {"$numberLong" : "1"}})); @@ -3114,8 +3123,8 @@ static void _test_encrypt_fle2_explicit(_mongocrypt_tester_t *tester) { { ee_testcase tc = {0}; tc.desc = "max is required to find int for range"; - tc.algorithm = MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR; - tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; tc.user_key_id = &keyABC_id; tc.contention_factor = OPT_I64(0); tc.range_opts = TEST_BSON(RAW_STRING({"min" : {"$numberInt" : "0"}, "sparsity" : {"$numberLong" : "1"}})); @@ -3148,7 +3157,7 @@ static void _test_encrypt_applies_default_state_collections(_mongocrypt_tester_t // TODO(MONGOCRYPT-572): This test uses the QEv1 protocol. Update this test for QEv2 or remove. Note: decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, false), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_BSON("{'find': 'coll'}")), ctx); ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); @@ -3183,7 +3192,7 @@ static void _test_encrypt_applies_default_state_collections(_mongocrypt_tester_t TEST_BSON("{'db.coll': { 'fields': [], 'escCollection': 'esc', " "'eccCollection': 'ecc', 'ecocCollection': 'ecoc'}}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_BSON("{'find': 'coll'}")), ctx); ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); @@ -3217,7 +3226,7 @@ static void _test_encrypt_applies_default_state_collections(_mongocrypt_tester_t TEST_BSON("{'fields': [], 'db.coll': {'escCollection': " "'esc', 'eccCollection': 'ecc', 'fields': []}}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_BSON("{'find': 'coll'}")), ctx); ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); @@ -3359,7 +3368,7 @@ static void _test_encrypt_fle2_delete_v1(_mongocrypt_tester_t *tester) { // decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, false), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); } mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -3416,7 +3425,7 @@ static void _test_encrypt_fle2_delete_v1(_mongocrypt_tester_t *tester) { // decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, false), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); } mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -3482,7 +3491,7 @@ static void _test_encrypt_fle2_delete_v1(_mongocrypt_tester_t *tester) { // decrypting // QEv1 is still supported. ASSERT_OK(mongocrypt_setopt_fle2v2(crypt, false), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); } mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -3613,7 +3622,7 @@ static void _test_encrypt_fle2_delete_v2(_mongocrypt_tester_t *tester) { mongocrypt_binary_destroy(localkey); mongocrypt_setopt_bypass_query_analysis(crypt); mongocrypt_setopt_fle2v2(crypt, true); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); } mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -3656,7 +3665,7 @@ static void _test_encrypt_fle2_delete_v2(_mongocrypt_tester_t *tester) { "encrypted-field-config-map.json")), crypt); mongocrypt_setopt_fle2v2(crypt, true); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); } mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -3715,7 +3724,7 @@ static void _test_encrypt_fle2_delete_v2(_mongocrypt_tester_t *tester) { crypt); mongocrypt_setopt_bypass_query_analysis(crypt); mongocrypt_setopt_fle2v2(crypt, true); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); } mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -4315,7 +4324,7 @@ static void _test_fle1_create_with_schema(_mongocrypt_tester_t *tester) { ASSERT_OK(mongocrypt_setopt_kms_provider_aws(crypt, "example", -1, "example", -1), crypt); ASSERT_OK(mongocrypt_setopt_schema_map(crypt, TEST_FILE("./test/data/fle1-create/with-schema/schema-map.json")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -4493,7 +4502,7 @@ static void _test_fle2_create(_mongocrypt_tester_t *tester) { crypt, TEST_FILE("./test/data/fle2-create/encrypted-field-config-map.json")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -4549,7 +4558,7 @@ static void _test_fle2_create_bypass_query_analysis(_mongocrypt_tester_t *tester TEST_FILE("./test/data/fle2-create/encrypted-field-config-map.json")), crypt); mongocrypt_setopt_bypass_query_analysis(crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); @@ -4650,6 +4659,823 @@ static void _test_fle1_collmod_without_jsonSchema(_mongocrypt_tester_t *tester) mongocrypt_destroy(crypt); } +#define BSON_STR(...) #__VA_ARGS__ + +static void _test_bulkWrite(_mongocrypt_tester_t *tester) { + if (!_aes_ctr_is_supported_by_os) { + printf("Common Crypto with no CTR support detected. Required by QEv2 encryption. Skipping."); + return; + } + + // local_kek is the KEK used to encrypt the keyMaterial in ./test/data/key-document-local.json + uint8_t local_kek_raw[MONGOCRYPT_KEY_LEN] = {0}; + char *local_kek = kms_message_raw_to_b64(local_kek_raw, sizeof(local_kek_raw)); + + // Test initializing bulkWrite commands. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_setopt_use_need_mongo_collinfo_with_db_state(crypt); + mongocrypt_setopt_kms_providers( + crypt, + TEST_BSON(BSON_STR({"local" : {"key" : {"$binary" : {"base64" : "%s", "subType" : "00"}}}}), local_kek)); + + ASSERT_OK(mongocrypt_setopt_encrypted_field_config_map( + crypt, + TEST_FILE("./test/data/bulkWrite/simple/encrypted-field-map.json")), + crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Successful case. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + mongocrypt_binary_t *cmd = TEST_BSON(BSON_STR({"bulkWrite" : 1, "nsInfo" : [ {"ns" : "db.coll"} ]})); + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, cmd), ctx); + mongocrypt_ctx_destroy(ctx); + } + + // No `nsInfo`. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + mongocrypt_binary_t *cmd = TEST_BSON(BSON_STR({"bulkWrite" : 1})); + ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, cmd), ctx, "failed to find namespace"); + mongocrypt_ctx_destroy(ctx); + } + + // `nsInfo` is not an array. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + mongocrypt_binary_t *cmd = TEST_BSON(BSON_STR({"bulkWrite" : 1, "nsInfo" : {"foo" : "bar"}})); + ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, cmd), ctx, "failed to find namespace"); + mongocrypt_ctx_destroy(ctx); + } + + // `nsInfo.ns` is not correct form. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + mongocrypt_binary_t *cmd = TEST_BSON(BSON_STR({"bulkWrite" : 1, "nsInfo" : [ {"ns" : "invalid"} ]})); + ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, cmd), ctx, "expected namespace to contain dot"); + mongocrypt_ctx_destroy(ctx); + } + + // `nsInfo` is empty. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + mongocrypt_binary_t *cmd = TEST_BSON(BSON_STR({"bulkWrite" : 1, "nsInfo" : []})); + ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, cmd), ctx, "failed to find namespace"); + mongocrypt_ctx_destroy(ctx); + } + + // `nsInfo` has more than one entry. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + mongocrypt_binary_t *cmd = + TEST_BSON(BSON_STR({"bulkWrite" : 1, "nsInfo" : [ {"ns" : "db.coll"}, {"ns" : "db.coll2"} ]})); + ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, cmd), ctx, "found more than one"); + mongocrypt_ctx_destroy(ctx); + } + + mongocrypt_destroy(crypt); + } + + // Test a bulkWrite with one namespace. + { + mongocrypt_t *crypt = mongocrypt_new(); + + mongocrypt_setopt_kms_providers( + crypt, + TEST_BSON(BSON_STR({"local" : {"key" : {"$binary" : {"base64" : "%s", "subType" : "00"}}}}), local_kek)); + + ASSERT_OK(mongocrypt_setopt_encrypted_field_config_map( + crypt, + TEST_FILE("./test/data/bulkWrite/simple/encrypted-field-map.json")), + crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, TEST_FILE("./test/data/bulkWrite/simple/cmd.json")), + ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); + { + mongocrypt_binary_t *cmd_to_mongocryptd = mongocrypt_binary_new(); + + ASSERT_OK(mongocrypt_ctx_mongo_op(ctx, cmd_to_mongocryptd), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/bulkWrite/simple/cmd-to-mongocryptd.json"), + cmd_to_mongocryptd); + mongocrypt_binary_destroy(cmd_to_mongocryptd); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/bulkWrite/simple/mongocryptd-reply.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/key-document-local.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + + // Match results. + bson_t out_bson; + ASSERT(_mongocrypt_binary_to_bson(out, &out_bson)); + mongocrypt_binary_t *pattern = TEST_FILE("./test/data/bulkWrite/simple/encrypted-payload-pattern.json"); + bson_t pattern_bson; + ASSERT(_mongocrypt_binary_to_bson(pattern, &pattern_bson)); + _assert_match_bson(&out_bson, &pattern_bson); + + mongocrypt_binary_destroy(out); + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test a bulkWrite with remote encryptedFields. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_setopt_use_need_mongo_collinfo_with_db_state(crypt); + + mongocrypt_setopt_kms_providers( + crypt, + TEST_BSON(BSON_STR({"local" : {"key" : {"$binary" : {"base64" : "%s", "subType" : "00"}}}}), local_kek)); + + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, TEST_FILE("./test/data/bulkWrite/simple/cmd.json")), + ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB); + { + // Ensure the requested database is obtained from `nsInfo` (and not "admin"). + const char *db = mongocrypt_ctx_mongo_db(ctx); + ASSERT_OK(db, ctx); + ASSERT_STREQUAL(db, "db"); + + { + mongocrypt_binary_t *cmd = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_mongo_op(ctx, cmd), ctx); + bson_t cmd_bson; + ASSERT(_mongocrypt_binary_to_bson(cmd, &cmd_bson)); + _assert_match_bson(&cmd_bson, TMP_BSON(BSON_STR({"name" : "test"}))); + mongocrypt_binary_destroy(cmd); + } + // Feed back response. + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/bulkWrite/simple/collinfo.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); + { + mongocrypt_binary_t *cmd_to_mongocryptd = mongocrypt_binary_new(); + + ASSERT_OK(mongocrypt_ctx_mongo_op(ctx, cmd_to_mongocryptd), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/bulkWrite/simple/cmd-to-mongocryptd.json"), + cmd_to_mongocryptd); + mongocrypt_binary_destroy(cmd_to_mongocryptd); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/bulkWrite/simple/mongocryptd-reply.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/key-document-local.json")), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + + // Match results. + bson_t out_bson; + ASSERT(_mongocrypt_binary_to_bson(out, &out_bson)); + mongocrypt_binary_t *pattern = TEST_FILE("./test/data/bulkWrite/simple/encrypted-payload-pattern.json"); + bson_t pattern_bson; + ASSERT(_mongocrypt_binary_to_bson(pattern, &pattern_bson)); + _assert_match_bson(&out_bson, &pattern_bson); + + mongocrypt_binary_destroy(out); + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test a bulkWrite with remote schema when MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB is not supported. + { + mongocrypt_t *crypt = mongocrypt_new(); + + mongocrypt_setopt_kms_providers( + crypt, + TEST_BSON(BSON_STR({"local" : {"key" : {"$binary" : {"base64" : "%s", "subType" : "00"}}}}), local_kek)); + + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + + ASSERT_FAILS( + mongocrypt_ctx_encrypt_init(ctx, "admin", -1, TEST_FILE("./test/data/bulkWrite/simple/cmd.json")), + ctx, + "Fetching remote collection information on separate databases is not supported. Try upgrading driver, or " + "specify a local schemaMap or encryptedFieldsMap."); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test a bulkWrite to an unencrypted collection. + { + mongocrypt_t *crypt = mongocrypt_new(); + // Opt-in to handling required state for fetching remote encryptedFields with `bulkWrite`. + mongocrypt_setopt_use_need_mongo_collinfo_with_db_state(crypt); + + mongocrypt_setopt_kms_providers( + crypt, + TEST_BSON(BSON_STR({"local" : {"key" : {"$binary" : {"base64" : "%s", "subType" : "00"}}}}), local_kek)); + + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK( + mongocrypt_ctx_encrypt_init(ctx, "admin", -1, TEST_FILE("./test/data/bulkWrite/unencrypted/cmd.json")), + ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB); + { + // Do not feed any response. + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); + { + mongocrypt_binary_t *cmd_to_mongocryptd = mongocrypt_binary_new(); + + ASSERT_OK(mongocrypt_ctx_mongo_op(ctx, cmd_to_mongocryptd), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/bulkWrite/unencrypted/cmd-to-mongocryptd.json"), + cmd_to_mongocryptd); + mongocrypt_binary_destroy(cmd_to_mongocryptd); + ASSERT_OK( + mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/bulkWrite/unencrypted/mongocryptd-reply.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + + // `expect` excludes `encryptionInformation`. + mongocrypt_binary_t *expect = TEST_FILE("./test/data/bulkWrite/unencrypted/payload.json"); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(expect, out); + + mongocrypt_binary_destroy(out); + } + + mongocrypt_ctx_destroy(ctx); + + // Test again to ensure the cached collinfo produces same result. + ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK( + mongocrypt_ctx_encrypt_init(ctx, "admin", -1, TEST_FILE("./test/data/bulkWrite/unencrypted/cmd.json")), + ctx); + + // MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB state is not entered. collinfo is loaded from cache. + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); + { + mongocrypt_binary_t *cmd_to_mongocryptd = mongocrypt_binary_new(); + + ASSERT_OK(mongocrypt_ctx_mongo_op(ctx, cmd_to_mongocryptd), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/bulkWrite/unencrypted/cmd-to-mongocryptd.json"), + cmd_to_mongocryptd); + mongocrypt_binary_destroy(cmd_to_mongocryptd); + ASSERT_OK( + mongocrypt_ctx_mongo_feed(ctx, TEST_FILE("./test/data/bulkWrite/unencrypted/mongocryptd-reply.json")), + ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + + // `expect` excludes `encryptionInformation`. + mongocrypt_binary_t *expect = TEST_FILE("./test/data/bulkWrite/unencrypted/payload.json"); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(expect, out); + + mongocrypt_binary_destroy(out); + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test a bulkWrite with bypassQueryAnalysis. Expect `encryptionInformation` is added, but query analysis is not + // consulted. + { + mongocrypt_t *crypt = mongocrypt_new(); + + mongocrypt_setopt_bypass_query_analysis(crypt); + + mongocrypt_setopt_kms_providers( + crypt, + TEST_BSON(BSON_STR({"local" : {"key" : {"$binary" : {"base64" : "%s", "subType" : "00"}}}}), local_kek)); + + ASSERT_OK(mongocrypt_setopt_encrypted_field_config_map( + crypt, + TEST_FILE("./test/data/bulkWrite/simple/encrypted-field-map.json")), + crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, TEST_FILE("./test/data/bulkWrite/simple/cmd.json")), + ctx); + + // Query analysis is not consulted. Immediately transitions to MONGOCRYPT_CTX_READY. + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + + // `expect` excludes `encryptionInformation`. + mongocrypt_binary_t *expect = TEST_FILE("./test/data/bulkWrite/bypassQueryAnalysis/payload.json"); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(expect, out); + mongocrypt_binary_destroy(out); + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test a bulkWrite with CSFLE (not supported by server) + { + mongocrypt_t *crypt = mongocrypt_new(); + + mongocrypt_setopt_kms_providers( + crypt, + TEST_BSON(BSON_STR({"local" : {"key" : {"$binary" : {"base64" : "%s", "subType" : "00"}}}}), local_kek)); + + // Associate a JSON schema to the collection to enable CSFLE. + ASSERT_OK(mongocrypt_setopt_schema_map(crypt, TEST_BSON(BSON_STR({"db.test" : {}}))), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "admin", -1, TEST_FILE("./test/data/bulkWrite/simple/cmd.json")), + ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); + { + mongocrypt_binary_t *cmd_to_mongocryptd = mongocrypt_binary_new(); + + ASSERT_OK(mongocrypt_ctx_mongo_op(ctx, cmd_to_mongocryptd), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_FILE("./test/data/bulkWrite/jsonSchema/cmd-to-mongocryptd.json"), + cmd_to_mongocryptd); + mongocrypt_binary_destroy(cmd_to_mongocryptd); + + // End the test here. At present, an error query analysis returns this error for `bulkWrite` with a + // `jsonSchema`: `The bulkWrite command only supports Queryable Encryption`. + // libmongocrypt deliberately does not error to enable possible future server support of CSFLE + // with bulkWrite without libmongocrypt changes. + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + bson_free(local_kek); +} + +// `_test_rangePreview_fails` tests that use of "rangePreview" errors when rangeV2 is opted-in. +static void _test_rangePreview_fails(_mongocrypt_tester_t *tester) { + // local_kek is the KEK used to encrypt the keyMaterial in ./test/data/key-document-local.json + uint8_t local_kek_raw[MONGOCRYPT_KEY_LEN] = {0}; + char *local_kek = kms_message_raw_to_b64(local_kek_raw, sizeof(local_kek_raw)); + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"local" : {"key" : {"$binary" : {"base64" : "%s", "subType" : "00"}}}}), local_kek); + + // Test setting 'rangePreview' as an explicit encryption algorithm results in error. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_setopt_kms_providers(crypt, kms_providers); + ASSERT_OK(mongocrypt_setopt_use_range_v2(crypt), crypt); + ASSERT_OK(mongocrypt_init(crypt), crypt); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(ctx, crypt); + ASSERT_FAILS(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGEPREVIEW_DEPRECATED_STR, -1), + ctx, + "Algorithm 'rangePreview' is deprecated"); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test setting 'rangePreview' as an explicit encryption queryType results in error. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_setopt_kms_providers(crypt, kms_providers); + ASSERT_OK(mongocrypt_setopt_use_range_v2(crypt), crypt); + ASSERT_OK(mongocrypt_init(crypt), crypt); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(ctx, crypt); + ASSERT_FAILS(mongocrypt_ctx_setopt_query_type(ctx, MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED_STR, -1), + ctx, + "Query type 'rangePreview' is deprecated"); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test setting 'rangePreview' from encryptedFields results in error. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_setopt_kms_providers(crypt, kms_providers); + ASSERT_OK(mongocrypt_setopt_use_range_v2(crypt), crypt); + ASSERT_OK(mongocrypt_setopt_encrypted_field_config_map( + crypt, + TEST_FILE("./test/data/fle2-insert-range/int32/encrypted-field-map.json")), // Uses 'rangePreview' + crypt); + ASSERT_OK(mongocrypt_init(crypt), crypt); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(ctx, crypt); + ASSERT_FAILS( + mongocrypt_ctx_encrypt_init(ctx, "db", -1, TEST_FILE("./test/data/fle2-insert-range/int32/cmd.json")), + ctx, + "Cannot use field 'encrypted' with 'rangePreview' queries"); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + bson_free(local_kek); +} + +// `autoencryption_test` defines a test for the automatic encryption context. +typedef struct { + const char *desc; + _test_rng_data_source rng_data; + mongocrypt_binary_t *cmd; + mongocrypt_binary_t *encrypted_field_map; + mongocrypt_binary_t *mongocryptd_reply; + mongocrypt_binary_t *keys_to_feed[3]; // NULL terminated list. + mongocrypt_binary_t *expect; +} autoencryption_test; + +static void autoencryption_test_run(autoencryption_test *aet) { + if (!_aes_ctr_is_supported_by_os) { + printf("Common Crypto with no CTR support detected. Skipping."); + return; + } + + printf(" auto_encryption test: '%s' ... begin\n", aet->desc); + + // Reset global counter for the `payloadId` to produce deterministic payloads. + extern void mc_reset_payloadId_for_testing(void); + mc_reset_payloadId_for_testing(); + + // Initialize mongocrypt_t. + mongocrypt_t *crypt = mongocrypt_new(); + { + mongocrypt_setopt_log_handler(crypt, _mongocrypt_stdout_log_fn, NULL); + + // Set "local" KMS provider. + { + // `localkey_data` is the KEK used to encrypt the keyMaterial in ./test/data/keys/ + char localkey_data[MONGOCRYPT_KEY_LEN] = {0}; + mongocrypt_binary_t *localkey = + mongocrypt_binary_new_from_data((uint8_t *)localkey_data, sizeof localkey_data); + ASSERT_OK(mongocrypt_setopt_kms_provider_local(crypt, localkey), crypt); + mongocrypt_binary_destroy(localkey); + } + + if (aet->rng_data.buf.len > 0) { + // Set deterministic random number generator. + ASSERT_OK(mongocrypt_setopt_crypto_hooks(crypt, + _std_hook_native_crypto_aes_256_cbc_encrypt, + _std_hook_native_crypto_aes_256_cbc_decrypt, + _test_rng_source, + _std_hook_native_hmac_sha512, + _std_hook_native_hmac_sha256, + _error_hook_native_sha256, + &aet->rng_data /* ctx */), + crypt); + } + + ASSERT_OK(mongocrypt_setopt_encrypted_field_config_map(crypt, aet->encrypted_field_map), crypt); + ASSERT_OK(mongocrypt_setopt_use_range_v2(crypt), crypt); + ASSERT_OK(mongocrypt_init(crypt), crypt); + } + + // Create the auto encryption context and run. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "db", -1, aet->cmd), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_MARKINGS); + { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, aet->mongocryptd_reply), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + { + for (mongocrypt_binary_t **iter = aet->keys_to_feed; *iter != NULL; iter++) { + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, *iter), ctx); + } + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + { + mongocrypt_binary_t *got = mongocrypt_binary_new(); + + bool ret = mongocrypt_ctx_finalize(ctx, got); + ASSERT_OK(ret, ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(aet->expect, got); + mongocrypt_binary_destroy(got); + } + + printf(" auto_encryption test: '%s' ... end\n", aet->desc); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +static void _test_no_trimFactor(_mongocrypt_tester_t *tester) { + if (!_aes_ctr_is_supported_by_os) { + printf("Common Crypto with no CTR support detected. Skipping."); + return; + } + + mongocrypt_binary_t *key123 = TEST_FILE("./test/data/keys/12345678123498761234123456789012-local-document.json"); + + // Test insert. + { + autoencryption_test aet = { + .desc = "missing trimFactor in mongocryptd reply for `insert` is OK", + .cmd = TEST_FILE("test/data/no-trimFactor/insert/cmd.json"), + .encrypted_field_map = TEST_FILE("test/data/no-trimFactor/insert/encrypted-field-map.json"), + .mongocryptd_reply = TEST_FILE("test/data/no-trimFactor/insert/mongocryptd-reply.json"), + .keys_to_feed = {key123}, + .expect = TEST_FILE("test/data/no-trimFactor/insert/encrypted-payload.json"), + }; + + // Set fixed random data for deterministic results. + mongocrypt_binary_t *rng_data = TEST_BIN(1024); + aet.rng_data = (_test_rng_data_source){.buf = {.data = rng_data->data, .len = rng_data->len}}; + + autoencryption_test_run(&aet); + } + + // Test find. + { + autoencryption_test aet = { + .desc = "missing trimFactor in mongocryptd reply for `find` is OK", + .cmd = TEST_FILE("test/data/no-trimFactor/find/cmd.json"), + .encrypted_field_map = TEST_FILE("test/data/no-trimFactor/find/encrypted-field-map.json"), + .mongocryptd_reply = TEST_FILE("test/data/no-trimFactor/find/mongocryptd-reply.json"), + .keys_to_feed = {key123}, + .expect = TEST_FILE("test/data/no-trimFactor/find/encrypted-payload.json"), + }; + + // Set fixed random data for deterministic results. + mongocrypt_binary_t *rng_data = TEST_BIN(1024); + aet.rng_data = (_test_rng_data_source){.buf = {.data = rng_data->data, .len = rng_data->len}}; + + autoencryption_test_run(&aet); + } +} + +// `lookup_payload_bson` looks up a payload from the BSON document `result` at path `path`. +// The BSON portion of the payload is parsed into `payload_bson`. +static void lookup_payload_bson(mongocrypt_binary_t *result, char *path, bson_t *payload_bson) { + bson_t result_bson; + ASSERT(_mongocrypt_binary_to_bson(result, &result_bson)); + + // Iterate to the path. + bson_iter_t iter; + ASSERT(bson_iter_init(&iter, &result_bson)); + if (!bson_iter_find_descendant(&iter, path, &iter)) { + TEST_ERROR("Unable to find path '%s'. Got: %s", path, tmp_json(&result_bson)); + } + + _mongocrypt_buffer_t buf; + ASSERT(_mongocrypt_buffer_from_binary_iter(&buf, &iter)); + ASSERT_CMPINT((int)buf.subtype, ==, (int)BSON_SUBTYPE_ENCRYPTED); + + // Expect a payload to start with an identifier byte. Expect the remainder to be BSON. + ASSERT_CMPUINT32(buf.len, >, 0); + ASSERT(bson_init_static(payload_bson, buf.data + 1, buf.len - 1)); +} + +// Test that the crypto params added in SERVER-91889 are sent for "range" payloads. +static void _test_range_sends_cryptoParams(_mongocrypt_tester_t *tester) { + if (!_aes_ctr_is_supported_by_os) { + printf("Common Crypto with no CTR support detected. Skipping."); + return; + } + + // Set up key data used for test. + _mongocrypt_buffer_t key123_id; + _mongocrypt_buffer_copy_from_hex(&key123_id, "12345678123498761234123456789012"); + mongocrypt_binary_t *key123 = TEST_FILE("./test/data/keys/12345678123498761234123456789012-local-document.json"); + // Use fixed random data for deterministic results. + mongocrypt_binary_t *rng_data = TEST_BIN(1024); + + // Test explicit insert. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for insert"; + tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data->data, .len = rng_data->len}}; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + tc.range_opts = TEST_BSON("{'min': 0, 'max': 1234567, 'sparsity': { '$numberLong': '3' }, 'trimFactor': 4}"); + tc.msg = TEST_BSON("{'v': 123456}"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-insert-int32/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON(BSON_STR({"sp" : 3, "tf" : 4, "mn" : 0, "mx" : 1234567, "pn" : {"$exists" : false}}))); + } + } + + // Test explicit insert with defaults. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for insert with correct defaults"; + tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data->data, .len = rng_data->len}}; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + // Use defaults for `sparsity` (2), and `trimFactor` (6). + tc.range_opts = TEST_BSON("{'min': 0, 'max': 1234567}"); + tc.msg = TEST_BSON("{'v': 123456}"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-insert-int32-defaults/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON(BSON_STR({"sp" : 2, "tf" : 6, "mn" : 0, "mx" : 1234567, "pn" : {"$exists" : false}}))); + } + } + + // Test explicit insert of double. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for insert for double"; + mongocrypt_binary_t *rng_data = TEST_BIN(1024); + tc.rng_data = (_test_rng_data_source){.buf = {.data = rng_data->data, .len = rng_data->len}}; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + tc.range_opts = TEST_BSON( + "{'min': 0.0, 'max': 1234567.0, 'precision': 2, 'sparsity': { '$numberLong': '3' }, 'trimFactor': 4}"); + tc.msg = TEST_BSON("{'v': 123456.0}"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-insert-double/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v", &payload_bson); + _assert_match_bson(&payload_bson, + TMP_BSON(BSON_STR({"sp" : 3, "tf" : 4, "mn" : 0.0, "mx" : 1234567.0, "pn" : 2}))); + } + } + + // Test explicit find. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for find with correct defaults"; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; + tc.is_expression = true; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + tc.range_opts = + TEST_BSON("{'min': 0, 'max': 1234567}"); // Use defaults for `sparsity` (2), and `trimFactor` (6). + tc.msg = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-find-int32-defaults/to-encrypt.json"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-find-int32-defaults/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v.$and.0.age.$gte", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON(BSON_STR({"sp" : 2, "tf" : 6, "mn" : 0, "mx" : 1234567, "pn" : {"$exists" : false}}))); + } + } + + // Test explicit find with defaults. + { + ee_testcase tc = {0}; + tc.desc = "'range' sends crypto params for find"; + tc.algorithm = MONGOCRYPT_ALGORITHM_RANGE_STR; + tc.query_type = MONGOCRYPT_QUERY_TYPE_RANGE_STR; + tc.is_expression = true; + tc.user_key_id = &key123_id; + tc.contention_factor = OPT_I64(1); + tc.range_opts = TEST_BSON("{'min': 0, 'max': 1234567, 'sparsity': { '$numberLong': '3' }, 'trimFactor': 4}"); + tc.msg = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-find-int32/to-encrypt.json"); + tc.keys_to_feed[0] = key123; + tc.expect = TEST_FILE("./test/data/range-sends-cryptoParams/explicit-find-int32/expected.json"); + tc.use_v2 = true; // Use QEv2 protocol. + tc.use_range_v2 = true; // Use RangeV2 protocol. + ee_testcase_run(&tc); + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(tc.expect, "v.$and.0.age.$gte", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON(BSON_STR({"sp" : 3, "tf" : 4, "mn" : 0, "mx" : 1234567, "pn" : {"$exists" : false}}))); + } + } + + // Test automatic insert of int32. + { + autoencryption_test aet = { + .desc = "'range' sends crypto params for insert", + .rng_data = {.buf = {.data = rng_data->data, .len = rng_data->len}}, + .cmd = TEST_FILE("./test/data/range-sends-cryptoParams/auto-insert-int32/cmd.json"), + .encrypted_field_map = + TEST_FILE("./test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-field-map.json"), + .mongocryptd_reply = + TEST_FILE("./test/data/range-sends-cryptoParams/auto-insert-int32/mongocryptd-reply.json"), + .keys_to_feed = {key123}, + .expect = TEST_FILE("./test/data/range-sends-cryptoParams/auto-insert-int32/encrypted-payload.json")}; + + autoencryption_test_run(&aet); + + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(aet.expect, "documents.0.encrypted", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON( + BSON_STR({"sp" : 2, "tf" : 6, "mn" : -2147483648, "mx" : 2147483647, "pn" : {"$exists" : false}}))); + } + } + + // Test automatic find of int32. + { + autoencryption_test aet = { + .desc = "'range' sends crypto params for find", + .cmd = TEST_FILE("./test/data/range-sends-cryptoParams/auto-find-int32/cmd.json"), + .encrypted_field_map = + TEST_FILE("./test/data/range-sends-cryptoParams/auto-find-int32/encrypted-field-map.json"), + .mongocryptd_reply = + TEST_FILE("./test/data/range-sends-cryptoParams/auto-find-int32/mongocryptd-reply.json"), + .keys_to_feed = {key123}, + .expect = TEST_FILE("./test/data/range-sends-cryptoParams/auto-find-int32/encrypted-payload.json")}; + + autoencryption_test_run(&aet); + + // Check the parameters are present in the final payload. + { + bson_t payload_bson; + lookup_payload_bson(aet.expect, "filter.$and.0.encrypted.$gte", &payload_bson); + _assert_match_bson( + &payload_bson, + TMP_BSON( + BSON_STR({"sp" : 2, "tf" : 6, "mn" : -2147483648, "mx" : 2147483647, "pn" : {"$exists" : false}}))); + } + } + + _mongocrypt_buffer_cleanup(&key123_id); +} + void _mongocrypt_tester_install_ctx_encrypt(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_explicit_encrypt_init); INSTALL_TEST(_test_encrypt_init); @@ -4729,4 +5555,8 @@ void _mongocrypt_tester_install_ctx_encrypt(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_encrypt_fle2_find_range_payload_decimal128); INSTALL_TEST(_test_encrypt_fle2_find_range_payload_decimal128_precision); #endif + INSTALL_TEST(_test_bulkWrite); + INSTALL_TEST(_test_rangePreview_fails); + INSTALL_TEST(_test_no_trimFactor); + INSTALL_TEST(_test_range_sends_cryptoParams); } diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c index 28a6e9f..bdd7d6e 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c @@ -753,7 +753,7 @@ static void _test_rewrap_many_datakey_kms_credentials(_mongocrypt_tester_t *test crypt = mongocrypt_new(); mongocrypt_setopt_use_need_kms_credentials_state(crypt); ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {}}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(ctx, crypt); @@ -828,7 +828,7 @@ static void _test_rewrap_many_datakey_kms_credentials(_mongocrypt_tester_t *test " 'accessKeyId': 'example'," " 'secretAccessKey': 'example'}}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(ctx, crypt); ASSERT_OK(mongocrypt_ctx_rewrap_many_datakey_init(ctx, TEST_BSON("{}")), ctx); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-setopt.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-setopt.c index 28703e0..495c625 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-setopt.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-setopt.c @@ -18,7 +18,9 @@ #include +#include "mc-range-encoding-private.h" #include "mongocrypt-binary-private.h" +#include "mongocrypt.h" #include "test-mongocrypt.h" /* An orphaned UTF-8 continuation byte (10xxxxxx) is malformed UTF-8. */ @@ -83,6 +85,13 @@ static char invalid_utf8[] = {(char)0x80, (char)0x00}; #define ASSERT_EX_DECRYPT_INIT_FAILS(bin, msg) ASSERT_FAILS(mongocrypt_ctx_explicit_decrypt_init(ctx, bin), ctx, msg); #define REFRESH \ + do { \ + mongocrypt_destroy(crypt); \ + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); \ + REFRESH_CTX; \ + } while (0) + +#define REFRESH_CTX \ do { \ mongocrypt_ctx_destroy(ctx); \ ctx = mongocrypt_ctx_new(crypt); \ @@ -808,28 +817,45 @@ static void _test_setopt_for_explicit_encrypt(_mongocrypt_tester_t *tester) { ASSERT_EX_ENCRYPT_INIT_FAILS(bson, "contention factor is required"); } - /* Contention factor is required for "rangePreview" algorithm. */ + /* Contention factor is required for "range" algorithm. */ { REFRESH; /* Set key ID to get past the 'either key id or key alt name required' * error */ ASSERT_KEY_ID_OK(uuid); ASSERT_OK(mongocrypt_ctx_setopt_algorithm_range(ctx, rangeopts), ctx); - ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGE_STR, -1), ctx); ASSERT_EX_ENCRYPT_INIT_FAILS(bson, "contention factor is required"); } - /* Range opts is required for "rangePreview" algorithm. */ + /* Range opts is required for "range" algorithm. */ { REFRESH; /* Set key ID to get past the 'either key id or key alt name required' * error */ ASSERT_KEY_ID_OK(uuid); ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx); - ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGE_STR, -1), ctx); ASSERT_EX_ENCRYPT_INIT_FAILS(bson, "range opts are required"); } + /* Sparsity is optional for rangeV2. */ + { + // Create a crypt with rangeV2 enabled. + mongocrypt_destroy(crypt); + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT | TESTER_MONGOCRYPT_WITH_RANGE_V2); + REFRESH_CTX; + /* Set key ID to get past the 'either key id or key alt name required' + * error */ + ASSERT_KEY_ID_OK(uuid); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm_range(ctx, TEST_BSON("{'min': 0, 'max': 1}")), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGE_STR, -1), ctx); + ASSERT(ctx->opts.rangeopts.set); + ASSERT_CMPINT64(ctx->opts.rangeopts.value.sparsity, ==, mc_FLERangeSparsityDefault); + ASSERT_EX_ENCRYPT_INIT_OK(bson); + } + /* Negative sparsity is prohibited. */ { REFRESH; @@ -841,27 +867,27 @@ static void _test_setopt_for_explicit_encrypt(_mongocrypt_tester_t *tester) { TEST_BSON("{'min': 0, 'max': 1, 'sparsity': { '$numberLong': '-1'}}")), ctx); ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx); - ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGE_STR, -1), ctx); ASSERT_EX_ENCRYPT_INIT_FAILS(bson, "sparsity must be non-negative"); } - /* Error if query_type == "rangePreview" and algorithm != "rangePreview". */ + /* Error if query_type == "range" and algorithm != "range". */ { REFRESH; ASSERT_KEY_ID_OK(uuid); ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_INDEXED_STR, -1); - ASSERT_QUERY_TYPE_OK(MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR, -1); + ASSERT_QUERY_TYPE_OK(MONGOCRYPT_QUERY_TYPE_RANGE_STR, -1); ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx); ASSERT_EX_ENCRYPT_INIT_FAILS(bson, "must match index_type"); } - /* Error if query_type == "rangePreview" for + /* Error if query_type == "range" for * mongocrypt_ctx_explicit_encrypt_init. */ { REFRESH; ASSERT_KEY_ID_OK(uuid); - ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR, -1); - ASSERT_QUERY_TYPE_OK(MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_STR, -1); + ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_RANGE_STR, -1); + ASSERT_QUERY_TYPE_OK(MONGOCRYPT_QUERY_TYPE_RANGE_STR, -1); ASSERT_OK( mongocrypt_ctx_setopt_algorithm_range(ctx, TEST_BSON("{'min': 0, 'max': 1, 'sparsity': {'$numberLong': '1'}}")), @@ -870,12 +896,88 @@ static void _test_setopt_for_explicit_encrypt(_mongocrypt_tester_t *tester) { ASSERT_EX_ENCRYPT_INIT_FAILS(bson, "Encrypt may not be used for range queries. Use EncryptExpression."); } + // Can't use "rangePreview" algorithm or query type with range V2. + { + mongocrypt_destroy(crypt); + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_WITH_RANGE_V2); + REFRESH_CTX; + ASSERT_KEY_ID_OK(uuid); + ASSERT_FAILS(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGEPREVIEW_DEPRECATED_STR, -1), + ctx, + "'rangePreview' is deprecated"); + + mongocrypt_destroy(crypt); + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_WITH_RANGE_V2); + REFRESH_CTX; + ASSERT_KEY_ID_OK(uuid); + ASSERT_FAILS(mongocrypt_ctx_setopt_query_type(ctx, MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED_STR, -1), + ctx, + "'rangePreview' is deprecated"); + } + + /* Error if query type == "rangePreview" and algorithm == "range" for range V1. */ + // Explanation: Algorithm "rangePreview" accepts both query type "rangePreview" (for compatibility) and "range" (new + // behavior), but algorithm "range" only accepts query type "range". This is because if we are using the new + // algorithm type, we don't need to support the deprecated name for compatibility. + { + REFRESH; + ASSERT_KEY_ID_OK(uuid); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm_range(ctx, rangeopts), ctx); + ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_RANGE_STR, -1); + ASSERT_QUERY_TYPE_OK(MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED_STR, -1); + ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx); + ASSERT_EX_ENCRYPT_EXPRESSION_INIT_FAILS(bson, "must match index_type"); + } + + /* If query type == "range" and algorithm == "rangePreview", succeeds for range V1 */ + { + REFRESH; + ASSERT_KEY_ID_OK(uuid); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm_range(ctx, rangeopts), ctx); + ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_RANGEPREVIEW_DEPRECATED_STR, -1); + ASSERT_QUERY_TYPE_OK(MONGOCRYPT_QUERY_TYPE_RANGE_STR, -1); + ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx); + ASSERT_EX_ENCRYPT_EXPRESSION_INIT_OK(bson); + } + + /* If query type == algorithm == "rangePreview", succeeds for range V1. */ + { + REFRESH; + ASSERT_KEY_ID_OK(uuid); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm_range(ctx, rangeopts), ctx); + ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_RANGEPREVIEW_DEPRECATED_STR, -1); + ASSERT_QUERY_TYPE_OK(MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED_STR, -1); + ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx); + ASSERT_EX_ENCRYPT_EXPRESSION_INIT_OK(bson); + } + + /* If query type == algorithm == "range", succeeds for both V2 and V1. */ + { + REFRESH; + ASSERT_KEY_ID_OK(uuid); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm_range(ctx, rangeopts), ctx); + ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_RANGE_STR, -1); + ASSERT_QUERY_TYPE_OK(MONGOCRYPT_QUERY_TYPE_RANGE_STR, -1); + ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx); + ASSERT_EX_ENCRYPT_EXPRESSION_INIT_OK(bson); + + mongocrypt_destroy(crypt); + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_WITH_RANGE_V2); + REFRESH_CTX; + ASSERT_KEY_ID_OK(uuid); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm_range(ctx, rangeopts), ctx); + ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_RANGE_STR, -1); + ASSERT_QUERY_TYPE_OK(MONGOCRYPT_QUERY_TYPE_RANGE_STR, -1); + ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx); + ASSERT_EX_ENCRYPT_EXPRESSION_INIT_OK(bson); + } + /* Error if query_type is unset for * mongocrypt_ctx_explicit_encrypt_expression_init. */ { REFRESH; ASSERT_KEY_ID_OK(uuid); - ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_RANGEPREVIEW_STR, -1); + ASSERT_ALGORITHM_OK(MONGOCRYPT_ALGORITHM_RANGE_STR, -1); ASSERT_OK( mongocrypt_ctx_setopt_algorithm_range(ctx, TEST_BSON("{'min': 0, 'max': 1, 'sparsity': {'$numberLong': '1'}}")), @@ -1065,7 +1167,7 @@ static void _test_createdatakey_with_wrong_kms_provider_helper(_mongocrypt_teste crypt = mongocrypt_new(); ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_provider), crypt); mongocrypt_setopt_use_need_kms_credentials_state(crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(kek)), ctx); ASSERT_FAILS(mongocrypt_ctx_datakey_init(ctx), ctx, "kms provider required by datakey is not configured"); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c index 3d201e1..3265c3a 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c @@ -16,6 +16,7 @@ #include +#include "kms_message/kms_b64.h" #include "mongocrypt-crypto-private.h" #include "mongocrypt-private.h" #include "test-mongocrypt.h" @@ -94,7 +95,7 @@ static void _test_create_data_key_with_provider(_mongocrypt_tester_t *tester, BSON_ASSERT(mongocrypt_ctx_state(ctx) == MONGOCRYPT_CTX_NEED_KMS); kms = mongocrypt_ctx_next_kms_ctx(ctx); BSON_ASSERT(kms); - ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/kms-encrypt-reply.txt")), kms); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/kms-aws/encrypt-response.txt")), kms); BSON_ASSERT(0 == mongocrypt_kms_ctx_bytes_needed(kms)); ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); } @@ -180,7 +181,7 @@ static void _test_datakey_custom_endpoint(_mongocrypt_tester_t *tester) { bin = mongocrypt_binary_new(); ASSERT_OK(mongocrypt_kms_ctx_message(kms_ctx, bin), ctx); BSON_ASSERT(NULL != strstr((char *)bin->data, "Host:example.com")); - ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-encrypt-reply.txt")), kms_ctx); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-aws/encrypt-response.txt")), kms_ctx); BSON_ASSERT(0 == mongocrypt_kms_ctx_bytes_needed(kms_ctx)); ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); @@ -210,7 +211,7 @@ static void _test_datakey_kms_per_ctx_credentials(_mongocrypt_tester_t *tester) crypt = mongocrypt_new(); mongocrypt_setopt_use_need_kms_credentials_state(crypt); ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {}}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_setopt_masterkey_aws(ctx, "region", -1, "cmk", -1), ctx); ASSERT_OK(mongocrypt_ctx_setopt_masterkey_aws_endpoint(ctx, "example.com", -1), ctx); @@ -228,7 +229,7 @@ static void _test_datakey_kms_per_ctx_credentials(_mongocrypt_tester_t *tester) bin = mongocrypt_binary_new(); ASSERT_OK(mongocrypt_kms_ctx_message(kms_ctx, bin), ctx); BSON_ASSERT(NULL != strstr((char *)bin->data, "Host:example.com")); - ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-encrypt-reply.txt")), kms_ctx); + ASSERT_OK(mongocrypt_kms_ctx_feed(kms_ctx, TEST_FILE("./test/data/kms-aws/encrypt-response.txt")), kms_ctx); BSON_ASSERT(0 == mongocrypt_kms_ctx_bytes_needed(kms_ctx)); ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); @@ -258,7 +259,7 @@ static void _test_datakey_kms_per_ctx_credentials_not_requested(_mongocrypt_test TEST_BSON("{'aws': {}, 'azure': {'tenantId': '', 'clientId': " "'', 'clientSecret': '' }}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON("{'provider': 'azure', 'keyVaultEndpoint': " @@ -280,13 +281,13 @@ static void _test_datakey_kms_per_ctx_credentials_local(_mongocrypt_tester_t *te mongocrypt_binary_t *bin; bson_t key_bson; bson_iter_t iter; - const char *local_kek = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + uint8_t local_kek_raw[MONGOCRYPT_KEY_LEN] = {0}; + char *local_kek = kms_message_raw_to_b64(local_kek_raw, sizeof(local_kek_raw)); crypt = mongocrypt_new(); mongocrypt_setopt_use_need_kms_credentials_state(crypt); ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'local': {}}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON("{'provider': 'local' }")), ctx); ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); @@ -310,6 +311,7 @@ static void _test_datakey_kms_per_ctx_credentials_local(_mongocrypt_tester_t *te mongocrypt_binary_destroy(bin); mongocrypt_ctx_destroy(ctx); mongocrypt_destroy(crypt); + bson_free(local_kek); } static void _test_datakey_custom_key_material(_mongocrypt_tester_t *tester) { @@ -377,8 +379,11 @@ static void _test_datakey_custom_key_material(_mongocrypt_tester_t *tester) { _mongocrypt_buffer_t decrypted_dek_buf; mongocrypt_binary_t decrypted_dek; + mc_kms_creds_t kc; + ASSERT(_mongocrypt_opts_kms_providers_lookup(&crypt->opts.kms_providers, "local", &kc)); + ASSERT(_mongocrypt_unwrap_key(crypt->crypto, - &crypt->opts.kms_providers.local.key, + &kc.value.local.key, &encrypted_dek_buf, &decrypted_dek_buf, crypt->status)); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-ctx.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-ctx.c index 64a20dc..156a159 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-ctx.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-ctx.c @@ -16,6 +16,9 @@ #include +#include "mongocrypt-buffer-private.h" +#include "mongocrypt-key-private.h" +#include "mongocrypt-kms-ctx-private.h" #include "mongocrypt-private.h" #include "test-mongocrypt-util.h" #include "test-mongocrypt.h" @@ -124,6 +127,7 @@ static void _test_mongocrypt_kms_ctx_kmip_register(_mongocrypt_tester_t *tester) endpoint, secretdata, KMS_KMIP_REQUEST_SECRETDATA_LENGTH, + "kmip", &crypt->log); ASSERT_OK_STATUS(ok, kms_ctx.status); @@ -221,6 +225,7 @@ static void _test_mongocrypt_kms_ctx_kmip_activate(_mongocrypt_tester_t *tester) ok = _mongocrypt_kms_ctx_init_kmip_activate(&kms_ctx, endpoint, (char *)SUCCESS_ACTIVATE_RESPONSE_UNIQUE_IDENTIFIER, + "kmip", &crypt->log); ASSERT_OK_STATUS(ok, kms_ctx.status); @@ -271,6 +276,7 @@ static const uint8_t GET_REQUEST[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0x10, 0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x02, 0x33, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static const char *const GET_REQUEST_UNIQUE_IDENTIFIER = "39"; + /* @@ -343,7 +349,11 @@ static void _test_mongocrypt_kms_ctx_kmip_get(_mongocrypt_tester_t *tester) { ASSERT_OK_STATUS(endpoint != NULL, status); crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); - ok = _mongocrypt_kms_ctx_init_kmip_get(&kms_ctx, endpoint, (char *)GET_REQUEST_UNIQUE_IDENTIFIER, &crypt->log); + ok = _mongocrypt_kms_ctx_init_kmip_get(&kms_ctx, + endpoint, + (char *)GET_REQUEST_UNIQUE_IDENTIFIER, + "kmip", + &crypt->log); ASSERT_OK_STATUS(ok, kms_ctx.status); bytes = mongocrypt_binary_new(); @@ -364,6 +374,412 @@ static void _test_mongocrypt_kms_ctx_kmip_get(_mongocrypt_tester_t *tester) { mongocrypt_destroy(crypt); } +/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +*/ +static const uint8_t CREATE_REQUEST[] = { + 0x42, 0x00, 0x78, 0x01, 0x00, 0x00, 0x01, 0x20, 0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0x38, 0x42, 0x00, 0x69, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x00, 0x0d, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0f, 0x01, + 0x00, 0x00, 0x00, 0xd8, 0x42, 0x00, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0xc0, 0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x91, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x42, 0x00, 0x08, 0x01, 0x00, + 0x00, 0x00, 0x30, 0x42, 0x00, 0x0a, 0x07, 0x00, 0x00, 0x00, 0x17, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x00, 0x42, 0x00, 0x0b, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x08, 0x01, 0x00, 0x00, + 0x00, 0x30, 0x42, 0x00, 0x0a, 0x07, 0x00, 0x00, 0x00, 0x14, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, 0x61, + 0x70, 0x68, 0x69, 0x63, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0b, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, + 0x30, 0x42, 0x00, 0x0a, 0x07, 0x00, 0x00, 0x00, 0x18, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x69, 0x63, 0x20, 0x55, 0x73, 0x61, 0x67, 0x65, 0x20, 0x4d, 0x61, 0x73, 0x6b, 0x42, 0x00, 0x0b, 0x02, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00}; + +/* + + + + + + + + + + + + + + + + + + +*/ +static const uint8_t SUCCESS_CREATE_RESPONSE[] = { + 0x42, 0x00, 0x7b, 0x01, 0x00, 0x00, 0x00, 0xa0, 0x42, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x00, 0x48, 0x42, 0x00, 0x69, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x65, 0x97, 0x02, 0x9a, 0x42, 0x00, 0x0d, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x42, 0x00, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x7c, 0x01, 0x00, + 0x00, 0x00, 0x20, 0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x03, 0x31, 0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const char *const SUCCESS_CREATE_RESPONSE_UNIQUE_IDENTIFIER = "108"; + +static void _test_mongocrypt_kms_ctx_kmip_create(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt; + mongocrypt_kms_ctx_t kms_ctx = {0}; + bool ok; + mongocrypt_binary_t *bytes; + _mongocrypt_buffer_t result; + mongocrypt_status_t *status; + _mongocrypt_endpoint_t *endpoint; + + status = mongocrypt_status_new(); + endpoint = _mongocrypt_endpoint_new("example.com", -1, NULL /* opts */, status); + ASSERT_OK_STATUS(endpoint != NULL, status); + + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + ok = _mongocrypt_kms_ctx_init_kmip_create(&kms_ctx, endpoint, "kmip", &crypt->log); + ASSERT_OK_STATUS(ok, kms_ctx.status); + + bytes = mongocrypt_binary_new(); + ok = mongocrypt_kms_ctx_message(&kms_ctx, bytes); + ASSERT_OK_STATUS(ok, kms_ctx.status); + + ASSERT_CMPBYTES(CREATE_REQUEST, + sizeof(CREATE_REQUEST), + mongocrypt_binary_data(bytes), + mongocrypt_binary_len(bytes)); + ASSERT_OK(kms_ctx_feed_all(&kms_ctx, SUCCESS_CREATE_RESPONSE, sizeof(SUCCESS_CREATE_RESPONSE)), &kms_ctx); + + ok = _mongocrypt_kms_ctx_result(&kms_ctx, &result); + ASSERT_OK_STATUS(ok, kms_ctx.status); + ASSERT_STREQUAL((char *)result.data, SUCCESS_CREATE_RESPONSE_UNIQUE_IDENTIFIER); + + mongocrypt_binary_destroy(bytes); + _mongocrypt_endpoint_destroy(endpoint); + mongocrypt_status_destroy(status); + _mongocrypt_kms_ctx_cleanup(&kms_ctx); + mongocrypt_destroy(crypt); +} + +/* + + + + + + + + + + + + + + + + + + + + + + +*/ +static const uint8_t ENCRYPT_REQUEST[] = { + 0x42, 0x00, 0x78, 0x01, 0x00, 0x00, 0x01, 0x20, 0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0x38, 0x42, 0x00, 0x69, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x00, 0x0d, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0f, 0x01, + 0x00, 0x00, 0x00, 0xd8, 0x42, 0x00, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0xc0, 0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x03, 0x31, 0x31, + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x40, 0x42, 0x00, 0x11, 0x05, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x5f, 0x05, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0xc5, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x42, 0x00, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x60, 0x6a, 0x4e, 0xde, 0x82, 0x3c, 0xe8, 0xa7, 0xf6, 0x2f, + 0x36, 0x1b, 0x39, 0x8f, 0x22, 0x4c, 0x58, 0x70, 0xd5, 0x82, 0xdc, 0xc7, 0xba, 0xb5, 0xd9, 0xe5, 0x84, 0x36, 0xdc, + 0xcc, 0x98, 0x2d, 0x36, 0xa5, 0x93, 0xb4, 0x3a, 0x99, 0x25, 0xfa, 0xe2, 0xe7, 0x4b, 0x0f, 0x57, 0xbf, 0xb6, 0xbf, + 0x5a, 0x17, 0xc7, 0xcc, 0x83, 0x2b, 0xc2, 0xba, 0x17, 0xed, 0x3d, 0xfb, 0x93, 0xe0, 0x0e, 0x47, 0x02, 0x8d, 0x6e, + 0xcf, 0x03, 0x7c, 0x49, 0x59, 0x22, 0xcf, 0x47, 0xaa, 0xb8, 0xa9, 0x37, 0x03, 0xc8, 0xa3, 0x53, 0x32, 0xfa, 0xb5, + 0x98, 0xa9, 0x2e, 0xc7, 0x8e, 0x19, 0x1f, 0x6e, 0x5f, 0xe5, 0x74 + +}; +static const uint8_t PLAINTEXT[] = {0x6a, 0x4e, 0xde, 0x82, 0x3c, 0xe8, 0xa7, 0xf6, 0x2f, 0x36, 0x1b, 0x39, 0x8f, 0x22, + 0x4c, 0x58, 0x70, 0xd5, 0x82, 0xdc, 0xc7, 0xba, 0xb5, 0xd9, 0xe5, 0x84, 0x36, 0xdc, + 0xcc, 0x98, 0x2d, 0x36, 0xa5, 0x93, 0xb4, 0x3a, 0x99, 0x25, 0xfa, 0xe2, 0xe7, 0x4b, + 0x0f, 0x57, 0xbf, 0xb6, 0xbf, 0x5a, 0x17, 0xc7, 0xcc, 0x83, 0x2b, 0xc2, 0xba, 0x17, + 0xed, 0x3d, 0xfb, 0x93, 0xe0, 0x0e, 0x47, 0x02, 0x8d, 0x6e, 0xcf, 0x03, 0x7c, 0x49, + 0x59, 0x22, 0xcf, 0x47, 0xaa, 0xb8, 0xa9, 0x37, 0x03, 0xc8, 0xa3, 0x53, 0x32, 0xfa, + 0xb5, 0x98, 0xa9, 0x2e, 0xc7, 0x8e, 0x19, 0x1f, 0x6e, 0x5f, 0xe5, 0x74 + +}; + +static const char *const KEK_UNIQUE_IDENTIFIER = "111"; + +/* + + + + + + + + + + + + + + + + + + + +*/ +static const uint8_t SUCCESS_ENCRYPT_RESPONSE[] = { + 0x42, 0x00, 0x7b, 0x01, 0x00, 0x00, 0x01, 0x20, 0x42, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x00, 0x48, 0x42, 0x00, 0x69, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x65, 0x97, 0x2c, 0xb1, 0x42, 0x00, 0x0d, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x00, + 0xc8, 0x42, 0x00, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x7c, 0x01, 0x00, + 0x00, 0x00, 0xa0, 0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x03, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x00, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x70, 0xe7, 0x0c, 0x4f, 0xe3, 0xc4, 0xe6, 0x7b, 0xe8, 0x69, 0x0a, 0xc0, + 0x59, 0x23, 0x69, 0xc4, 0xfd, 0xf1, 0x1f, 0x44, 0xeb, 0xd4, 0x56, 0x78, 0x0d, 0x56, 0x13, 0xb7, 0x8c, 0xec, 0x60, + 0x2c, 0x5a, 0x12, 0x99, 0xe0, 0x41, 0x6c, 0x67, 0x28, 0xe2, 0x27, 0x73, 0x0d, 0x2b, 0xd1, 0x86, 0xdc, 0xce, 0xf1, + 0xee, 0x8c, 0x3a, 0x58, 0x52, 0x0b, 0x2e, 0x4f, 0x6c, 0x1b, 0x4c, 0x46, 0xe1, 0x28, 0x3b, 0x79, 0xb4, 0x5c, 0xc5, + 0xa8, 0x72, 0x07, 0xf3, 0xec, 0x8d, 0xf5, 0x39, 0xae, 0x38, 0x63, 0x37, 0xd3, 0x05, 0xf7, 0x91, 0xed, 0x13, 0xfd, + 0x7f, 0xeb, 0x84, 0x8e, 0xde, 0xf9, 0x61, 0x32, 0x03, 0x75, 0xd1, 0x9d, 0x88, 0x37, 0xe3, 0x9a, 0x57, 0x7d, 0xca, + 0x3a, 0xd6, 0x52, 0x83, 0x01, 0x12, 0x42, 0x00, 0x3d, 0x08, 0x00, 0x00, 0x00, 0x10, 0x26, 0x77, 0xc2, 0x60, 0xed, + 0xc3, 0x5f, 0x73, 0x6c, 0x23, 0x3e, 0x74, 0x1e, 0x18, 0x24, 0x5f}; + +/* Encrypted data with server-generated IV prepended */ +static const uint8_t IV_CIPHERTEXT[] = { + 0x26, 0x77, 0xc2, 0x60, 0xed, 0xc3, 0x5f, 0x73, 0x6c, 0x23, 0x3e, 0x74, 0x1e, 0x18, 0x24, 0x5f, 0xe7, 0x0c, 0x4f, + 0xe3, 0xc4, 0xe6, 0x7b, 0xe8, 0x69, 0x0a, 0xc0, 0x59, 0x23, 0x69, 0xc4, 0xfd, 0xf1, 0x1f, 0x44, 0xeb, 0xd4, 0x56, + 0x78, 0x0d, 0x56, 0x13, 0xb7, 0x8c, 0xec, 0x60, 0x2c, 0x5a, 0x12, 0x99, 0xe0, 0x41, 0x6c, 0x67, 0x28, 0xe2, 0x27, + 0x73, 0x0d, 0x2b, 0xd1, 0x86, 0xdc, 0xce, 0xf1, 0xee, 0x8c, 0x3a, 0x58, 0x52, 0x0b, 0x2e, 0x4f, 0x6c, 0x1b, 0x4c, + 0x46, 0xe1, 0x28, 0x3b, 0x79, 0xb4, 0x5c, 0xc5, 0xa8, 0x72, 0x07, 0xf3, 0xec, 0x8d, 0xf5, 0x39, 0xae, 0x38, 0x63, + 0x37, 0xd3, 0x05, 0xf7, 0x91, 0xed, 0x13, 0xfd, 0x7f, 0xeb, 0x84, 0x8e, 0xde, 0xf9, 0x61, 0x32, 0x03, 0x75, 0xd1, + 0x9d, 0x88, 0x37, 0xe3, 0x9a, 0x57, 0x7d, 0xca, 0x3a, 0xd6, 0x52, 0x83, 0x01, 0x12 + +}; + +static void _test_mongocrypt_kms_ctx_kmip_encrypt(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt; + mongocrypt_kms_ctx_t kms_ctx = {0}; + bool ok; + mongocrypt_binary_t *bytes; + _mongocrypt_buffer_t result; + mongocrypt_status_t *status; + _mongocrypt_endpoint_t *endpoint; + + _mongocrypt_buffer_t plaintext = {0}; + ASSERT(_mongocrypt_buffer_copy_from_data_and_size(&plaintext, PLAINTEXT, sizeof(PLAINTEXT))) + + status = mongocrypt_status_new(); + endpoint = _mongocrypt_endpoint_new("example.com", -1, NULL /* opts */, status); + ASSERT_OK_STATUS(endpoint != NULL, status); + + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + ok = _mongocrypt_kms_ctx_init_kmip_encrypt(&kms_ctx, + endpoint, + (char *)KEK_UNIQUE_IDENTIFIER, + "kmip", + &plaintext, + &crypt->log); + ASSERT_OK_STATUS(ok, kms_ctx.status); + + bytes = mongocrypt_binary_new(); + ok = mongocrypt_kms_ctx_message(&kms_ctx, bytes); + ASSERT_OK_STATUS(ok, kms_ctx.status); + + ASSERT_CMPBYTES(ENCRYPT_REQUEST, + sizeof(ENCRYPT_REQUEST), + mongocrypt_binary_data(bytes), + mongocrypt_binary_len(bytes)); + ASSERT_OK(kms_ctx_feed_all(&kms_ctx, SUCCESS_ENCRYPT_RESPONSE, sizeof(SUCCESS_ENCRYPT_RESPONSE)), &kms_ctx); + + ok = _mongocrypt_kms_ctx_result(&kms_ctx, &result); + ASSERT_OK_STATUS(ok, kms_ctx.status); + ASSERT_CMPBYTES(result.data, result.len, IV_CIPHERTEXT, sizeof(IV_CIPHERTEXT)); + + _mongocrypt_buffer_cleanup(&plaintext); + mongocrypt_binary_destroy(bytes); + _mongocrypt_endpoint_destroy(endpoint); + mongocrypt_status_destroy(status); + _mongocrypt_kms_ctx_cleanup(&kms_ctx); + mongocrypt_destroy(crypt); +} + +/* + + + + + + + + + + + + + + + + + + + + + + +*/ +static const uint8_t DECRYPT_REQUEST[] = { + 0x42, 0x00, 0x78, 0x01, 0x00, 0x00, 0x01, 0x38, 0x42, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0x38, 0x42, 0x00, 0x69, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x00, 0x0d, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0f, 0x01, + 0x00, 0x00, 0x00, 0xf0, 0x42, 0x00, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x42, 0x00, 0x79, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x03, 0x31, 0x31, + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x30, 0x42, 0x00, 0x11, 0x05, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x5f, 0x05, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x28, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x70, 0xe7, 0x0c, 0x4f, 0xe3, 0xc4, 0xe6, + 0x7b, 0xe8, 0x69, 0x0a, 0xc0, 0x59, 0x23, 0x69, 0xc4, 0xfd, 0xf1, 0x1f, 0x44, 0xeb, 0xd4, 0x56, 0x78, 0x0d, 0x56, + 0x13, 0xb7, 0x8c, 0xec, 0x60, 0x2c, 0x5a, 0x12, 0x99, 0xe0, 0x41, 0x6c, 0x67, 0x28, 0xe2, 0x27, 0x73, 0x0d, 0x2b, + 0xd1, 0x86, 0xdc, 0xce, 0xf1, 0xee, 0x8c, 0x3a, 0x58, 0x52, 0x0b, 0x2e, 0x4f, 0x6c, 0x1b, 0x4c, 0x46, 0xe1, 0x28, + 0x3b, 0x79, 0xb4, 0x5c, 0xc5, 0xa8, 0x72, 0x07, 0xf3, 0xec, 0x8d, 0xf5, 0x39, 0xae, 0x38, 0x63, 0x37, 0xd3, 0x05, + 0xf7, 0x91, 0xed, 0x13, 0xfd, 0x7f, 0xeb, 0x84, 0x8e, 0xde, 0xf9, 0x61, 0x32, 0x03, 0x75, 0xd1, 0x9d, 0x88, 0x37, + 0xe3, 0x9a, 0x57, 0x7d, 0xca, 0x3a, 0xd6, 0x52, 0x83, 0x01, 0x12, 0x42, 0x00, 0x3d, 0x08, 0x00, 0x00, 0x00, 0x10, + 0x26, 0x77, 0xc2, 0x60, 0xed, 0xc3, 0x5f, 0x73, 0x6c, 0x23, 0x3e, 0x74, 0x1e, 0x18, 0x24, 0x5f + +}; + +/* + + + + + + + + + + + + + + + + + + +*/ +static const uint8_t SUCCESS_DECRYPT_RESPONSE[] = { + 0x42, 0x00, 0x7b, 0x01, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x00, 0x48, 0x42, 0x00, 0x69, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x65, 0x97, 0x2f, 0x46, 0x42, 0x00, 0x0d, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x00, + 0xa0, 0x42, 0x00, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x7c, 0x01, 0x00, + 0x00, 0x00, 0x78, 0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x03, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x00, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x60, 0x6a, 0x4e, 0xde, 0x82, 0x3c, 0xe8, 0xa7, 0xf6, 0x2f, 0x36, 0x1b, + 0x39, 0x8f, 0x22, 0x4c, 0x58, 0x70, 0xd5, 0x82, 0xdc, 0xc7, 0xba, 0xb5, 0xd9, 0xe5, 0x84, 0x36, 0xdc, 0xcc, 0x98, + 0x2d, 0x36, 0xa5, 0x93, 0xb4, 0x3a, 0x99, 0x25, 0xfa, 0xe2, 0xe7, 0x4b, 0x0f, 0x57, 0xbf, 0xb6, 0xbf, 0x5a, 0x17, + 0xc7, 0xcc, 0x83, 0x2b, 0xc2, 0xba, 0x17, 0xed, 0x3d, 0xfb, 0x93, 0xe0, 0x0e, 0x47, 0x02, 0x8d, 0x6e, 0xcf, 0x03, + 0x7c, 0x49, 0x59, 0x22, 0xcf, 0x47, 0xaa, 0xb8, 0xa9, 0x37, 0x03, 0xc8, 0xa3, 0x53, 0x32, 0xfa, 0xb5, 0x98, 0xa9, + 0x2e, 0xc7, 0x8e, 0x19, 0x1f, 0x6e, 0x5f, 0xe5, 0x74}; + +static void _test_mongocrypt_kms_ctx_kmip_decrypt(_mongocrypt_tester_t *tester) { + mongocrypt_t *crypt; + mongocrypt_kms_ctx_t kms_ctx = {0}; + bool ok; + mongocrypt_binary_t *bytes; + _mongocrypt_buffer_t result; + mongocrypt_status_t *status; + _mongocrypt_endpoint_t *endpoint; + + /* should be _mongocrypt_key_doc_t key_doc = {0} + * but doesn't compile on Ubuntu 16 due to https://bugs.llvm.org/show_bug.cgi?id=21629 */ + _mongocrypt_key_doc_t key_doc; + memset(&key_doc, 0, sizeof(key_doc)); + + key_doc.kek.kms_provider = MONGOCRYPT_KMS_PROVIDER_KMIP; + key_doc.kek.provider.kmip.delegated = true; + key_doc.kek.provider.kmip.key_id = (char *)KEK_UNIQUE_IDENTIFIER; + ASSERT(_mongocrypt_buffer_copy_from_data_and_size(&key_doc.key_material, IV_CIPHERTEXT, sizeof(IV_CIPHERTEXT))) + + status = mongocrypt_status_new(); + endpoint = _mongocrypt_endpoint_new("example.com", -1, NULL /* opts */, status); + ASSERT_OK_STATUS(endpoint != NULL, status); + + crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + ok = _mongocrypt_kms_ctx_init_kmip_decrypt(&kms_ctx, endpoint, "kmip", &key_doc, &crypt->log); + ASSERT_OK_STATUS(ok, kms_ctx.status); + + bytes = mongocrypt_binary_new(); + ok = mongocrypt_kms_ctx_message(&kms_ctx, bytes); + ASSERT_OK_STATUS(ok, kms_ctx.status); + + ASSERT_CMPBYTES(DECRYPT_REQUEST, + sizeof(DECRYPT_REQUEST), + mongocrypt_binary_data(bytes), + mongocrypt_binary_len(bytes)); + ASSERT_OK(kms_ctx_feed_all(&kms_ctx, SUCCESS_DECRYPT_RESPONSE, sizeof(SUCCESS_DECRYPT_RESPONSE)), &kms_ctx); + + ok = _mongocrypt_kms_ctx_result(&kms_ctx, &result); + ASSERT_OK_STATUS(ok, kms_ctx.status); + ASSERT_CMPBYTES(result.data, result.len, PLAINTEXT, sizeof(PLAINTEXT)); + + _mongocrypt_buffer_cleanup(&key_doc.key_material); + mongocrypt_binary_destroy(bytes); + _mongocrypt_endpoint_destroy(endpoint); + mongocrypt_status_destroy(status); + _mongocrypt_kms_ctx_cleanup(&kms_ctx); + mongocrypt_destroy(crypt); +} + static void _test_mongocrypt_kms_ctx_get_kms_provider(_mongocrypt_tester_t *tester) { mongocrypt_t *crypt; mongocrypt_kms_ctx_t kms_ctx = {0}; @@ -380,11 +796,10 @@ static void _test_mongocrypt_kms_ctx_get_kms_provider(_mongocrypt_tester_t *test ok = _mongocrypt_kms_ctx_init_kmip_activate(&kms_ctx, endpoint, (char *)SUCCESS_ACTIVATE_RESPONSE_UNIQUE_IDENTIFIER, + "kmip", &crypt->log); ASSERT_OK_STATUS(ok, kms_ctx.status); - ASSERT_STREQUAL(mongocrypt_kms_ctx_get_kms_provider(&kms_ctx, NULL), "kmip"); - ASSERT_STREQUAL(mongocrypt_kms_ctx_get_kms_provider(&kms_ctx, &len), "kmip"); ASSERT_CMPINT(len, ==, 4); @@ -412,6 +827,7 @@ static void _test_mongocrypt_kms_ctx_default_port(_mongocrypt_tester_t *tester) ASSERT_OK(_mongocrypt_kms_ctx_init_kmip_activate(&kms_ctx, endpoint, (char *)SUCCESS_ACTIVATE_RESPONSE_UNIQUE_IDENTIFIER, + "kmip", &crypt->log), &kms_ctx); ASSERT_OK(mongocrypt_kms_ctx_endpoint(&kms_ctx, &kms_ctx_endpoint), &kms_ctx); @@ -427,6 +843,7 @@ static void _test_mongocrypt_kms_ctx_default_port(_mongocrypt_tester_t *tester) ASSERT_OK(_mongocrypt_kms_ctx_init_kmip_activate(&kms_ctx, endpoint, (char *)SUCCESS_ACTIVATE_RESPONSE_UNIQUE_IDENTIFIER, + "kmip", &crypt->log), &kms_ctx); ASSERT_OK(mongocrypt_kms_ctx_endpoint(&kms_ctx, &kms_ctx_endpoint), &kms_ctx); @@ -454,6 +871,7 @@ static void _test_mongocrypt_kms_ctx_feed_empty_bytes(_mongocrypt_tester_t *test ASSERT_OK(_mongocrypt_kms_ctx_init_kmip_activate(&kms_ctx, endpoint, (char *)SUCCESS_ACTIVATE_RESPONSE_UNIQUE_IDENTIFIER, + "kmip", &crypt->log), &kms_ctx); @@ -471,6 +889,9 @@ void _mongocrypt_tester_install_kms_ctx(_mongocrypt_tester_t *tester) { INSTALL_TEST(_test_mongocrypt_kms_ctx_kmip_register); INSTALL_TEST(_test_mongocrypt_kms_ctx_kmip_activate); INSTALL_TEST(_test_mongocrypt_kms_ctx_kmip_get); + INSTALL_TEST(_test_mongocrypt_kms_ctx_kmip_create); + INSTALL_TEST(_test_mongocrypt_kms_ctx_kmip_encrypt); + INSTALL_TEST(_test_mongocrypt_kms_ctx_kmip_decrypt); INSTALL_TEST(_test_mongocrypt_kms_ctx_get_kms_provider); INSTALL_TEST(_test_mongocrypt_kms_ctx_default_port); INSTALL_TEST(_test_mongocrypt_kms_ctx_feed_empty_bytes); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-log.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-log.c index 4a73f95..bef2be5 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-log.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-log.c @@ -104,7 +104,7 @@ static void _test_no_log(_mongocrypt_tester_t *tester) { status = mongocrypt_status_new(); crypt = mongocrypt_new(); mongocrypt_setopt_kms_provider_aws(crypt, "example", -1, "example", -1); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); _mongocrypt_log(&crypt->log, MONGOCRYPT_LOG_LEVEL_FATAL, "Please don't log"); mongocrypt_status_destroy(status); mongocrypt_destroy(crypt); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c index 9a9c56f..28ec047 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c @@ -17,8 +17,15 @@ /* For each field, check a valid value, invalid value, missing value */ #include "bson/bson.h" +#include "mc-fle-blob-subtype-private.h" +#include "mc-tokens-private.h" +#include "mongocrypt-buffer-private.h" +#include "mongocrypt-ciphertext-private.h" #include "mongocrypt-marking-private.h" +#include "mongocrypt.h" +#include "test-mongocrypt-assert.h" #include "test-mongocrypt.h" +#include /* Create a basis marking buffer with valid values for the given fields. */ static void _make_marking(bson_t *bson, _mongocrypt_buffer_t *buf) { @@ -187,10 +194,24 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te const char *expectedMinCover; mc_optional_int64_t sparsity; const char *expectedError; + const char *expectedErrorAtParseTime; + bool disableRangeV2; } testcase_t; testcase_t tests[] = { - {.description = "Int32 Bounds included", + {.description = "Range V2 disabled w/ trim factor fails", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberInt" : "7"}, + "lbIncluded" : true, + "upperBound" : {"$numberInt" : "32"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 + }), + .disableRangeV2 = true, + .expectedErrorAtParseTime = "'trimFactor' is not supported for QE range v1"}, + {.description = "Range V2 disabled w/ no trim factor succeeds", .findSpecJSON = RAW_STRING({ "lowerBound" : {"$numberInt" : "7"}, "lbIncluded" : true, @@ -199,6 +220,21 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "indexMin" : {"$numberInt" : "0"}, "indexMax" : {"$numberInt" : "32"} }), + .disableRangeV2 = true, + .expectedMinCover = "000111\n" + "001\n" + "01\n" + "100000\n"}, + {.description = "Int32 Bounds included", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberInt" : "7"}, + "lbIncluded" : true, + "upperBound" : {"$numberInt" : "32"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 + }), .expectedMinCover = "000111\n" "001\n" "01\n" @@ -211,7 +247,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberInt" : "32"}, "ubIncluded" : false, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 }), .expectedMinCover = "001\n" "01\n"}, @@ -222,7 +259,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberInt" : "32"}, "ubIncluded" : false, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 }), .expectedMinCover = "000111\n" "001\n" @@ -234,7 +272,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberInt" : "32"}, "ubIncluded" : true, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 }), .expectedMinCover = "001\n" "01\n" @@ -246,7 +285,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberDouble" : "Infinity"}, "ubIncluded" : true, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 }), .expectedMinCover = "000111\n" "001\n" @@ -259,7 +299,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberInt" : "8"}, "ubIncluded" : true, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 }), .expectedMinCover = "000\n" "001000\n"}, @@ -270,10 +311,150 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberDouble" : "Infinity"}, "ubIncluded" : true, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 + }), + .expectedMinCover = "0\n" + "100000\n"}, + {.description = "Int32 mincover=root no trimming", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "31"}, + "trimFactor" : 0 + }), + .expectedMinCover = "root\n"}, + {.description = "Int32 mincover=root TF=1", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "31"}, + "trimFactor" : 1 }), .expectedMinCover = "0\n" + "1\n"}, + {.description = "Int32 mincover=root TF=3", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "31"}, + "trimFactor" : 3 + }), + .expectedMinCover = "000\n" + "001\n" + "010\n" + "011\n" + "100\n" + "101\n" + "110\n" + "111\n"}, + {.description = "Int32 infinite both bounds SP=2", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 + }), + .sparsity = OPT_I64(2), + .expectedMinCover = "00\n" + "01\n" "100000\n"}, + {.description = "Int32 infinite both bounds TF=1", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 1 + }), + .expectedMinCover = "0\n" + "100000\n"}, + {.description = "Int32 infinite both bounds TF=2", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 2 + }), + .expectedMinCover = "00\n" + "01\n" + "100000\n"}, + + {.description = "Int32 infinite both bounds TF=3", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 3 + }), + .expectedMinCover = "000\n" + "001\n" + "010\n" + "011\n" + "100000\n"}, + {.description = "Int32 infinite both bounds SP=2 TF=3", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 3 + }), + .sparsity = OPT_I64(2), + .expectedMinCover = "0000\n" + "0001\n" + "0010\n" + "0011\n" + "0100\n" + "0101\n" + "0110\n" + "0111\n" + "100000\n"}, + {.description = "Too large trim factor fails", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 6 + }), + .expectedError = + "Trim factor must be less than the number of bits (6) used to represent an element of the domain"}, + {.description = "Negative trim factor fails", + .findSpecJSON = RAW_STRING({ + "lowerBound" : {"$numberDouble" : "-Infinity"}, + "lbIncluded" : true, + "upperBound" : {"$numberDouble" : "Infinity"}, + "ubIncluded" : true, + "indexMin" : {"$numberInt" : "0"}, + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : -1 + }), + .expectedErrorAtParseTime = "'trimFactor' must be non-negative"}, {.description = "Int64 Bounds included", .findSpecJSON = RAW_STRING({ "lowerBound" : {"$numberLong" : "0"}, @@ -281,7 +462,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberLong" : "823"}, "ubIncluded" : true, "indexMin" : {"$numberLong" : "-1000000000000000"}, - "indexMax" : {"$numberLong" : "8070450532247928832"} + "indexMax" : {"$numberLong" : "8070450532247928832"}, + "trimFactor" : 0 }), .expectedMinCover = "000000000000011100011010111111010100100110001101000000\n" "00000000000001110001101011111101010010011000110100000100\n" @@ -299,7 +481,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberLong" : "823"}, "ubIncluded" : false, "indexMin" : {"$numberLong" : "-1000000000000000"}, - "indexMax" : {"$numberLong" : "8070450532247928832"} + "indexMax" : {"$numberLong" : "8070450532247928832"}, + "trimFactor" : 0 }), .expectedMinCover = "000000000000011100011010111111010100100110001101000000000000001\n" "00000000000001110001101011111101010010011000110100000000000001\n" @@ -332,7 +515,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberLong" : "823"}, "ubIncluded" : false, "indexMin" : {"$numberLong" : "-1000000000000000"}, - "indexMax" : {"$numberLong" : "8070450532247928832"} + "indexMax" : {"$numberLong" : "8070450532247928832"}, + "trimFactor" : 0 }), .expectedMinCover = "000000000000011100011010111111010100100110001101000000\n" "00000000000001110001101011111101010010011000110100000100\n" @@ -353,7 +537,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberLong" : "823"}, "ubIncluded" : true, "indexMin" : {"$numberLong" : "-1000000000000000"}, - "indexMax" : {"$numberLong" : "8070450532247928832"} + "indexMax" : {"$numberLong" : "8070450532247928832"}, + "trimFactor" : 0 }), .expectedMinCover = "000000000000011100011010111111010100100110001101000000000000001\n" "00000000000001110001101011111101010010011000110100000000000001\n" @@ -382,7 +567,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberDouble" : "Infinity"}, "ubIncluded" : true, "indexMin" : {"$numberLong" : "0"}, - "indexMax" : {"$numberLong" : "7"} + "indexMax" : {"$numberLong" : "7"}, + "trimFactor" : 0 }), .expectedMinCover = "001\n" "01\n" @@ -394,7 +580,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberLong" : "5"}, "ubIncluded" : true, "indexMin" : {"$numberLong" : "0"}, - "indexMax" : {"$numberLong" : "7"} + "indexMax" : {"$numberLong" : "7"}, + "trimFactor" : 0 }), .expectedMinCover = "0\n" "10\n"}, @@ -405,7 +592,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberDouble" : "Infinity"}, "ubIncluded" : true, "indexMin" : {"$numberLong" : "0"}, - "indexMax" : {"$numberLong" : "7"} + "indexMax" : {"$numberLong" : "7"}, + "trimFactor" : 0 }), .expectedMinCover = "root\n"}, {.description = "Mismatched types", @@ -415,7 +603,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberLong" : "2"}, "ubIncluded" : true, "indexMin" : {"$numberLong" : "0"}, - "indexMax" : {"$numberLong" : "7"} + "indexMax" : {"$numberLong" : "7"}, + "trimFactor" : 0 }), .expectedError = "expected lowerBound to match index type"}, {.description = "Int32 exclusive lower bound > upper bound", @@ -425,7 +614,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberInt" : "7"}, "ubIncluded" : true, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 }), .expectedError = "must be less than or equal to range max"}, {.description = "Int64 exclusive lower bound > upper bound", @@ -435,7 +625,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberLong" : "7"}, "ubIncluded" : true, "indexMin" : {"$numberLong" : "0"}, - "indexMax" : {"$numberLong" : "32"} + "indexMax" : {"$numberLong" : "32"}, + "trimFactor" : 0 }), .expectedError = "must be less than or equal to range max"}, {.description = "Int32 exclusive upper bound < lower bound", @@ -445,7 +636,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberInt" : "7"}, "ubIncluded" : false, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 }), .expectedError = "must be less than or equal to range max"}, {.description = "Int64 exclusive upper bound < lower bound", @@ -455,7 +647,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberLong" : "7"}, "ubIncluded" : false, "indexMin" : {"$numberLong" : "0"}, - "indexMax" : {"$numberLong" : "32"} + "indexMax" : {"$numberLong" : "32"}, + "trimFactor" : 0 }), .expectedError = "must be less than or equal to range max"}, {.description = "Int32 exclusive bounds cross", @@ -465,7 +658,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberInt" : "7"}, "ubIncluded" : false, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 }), .expectedError = "must be less than or equal to range max"}, {.description = "Int64 exclusive bounds cross", @@ -475,7 +669,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberLong" : "7"}, "ubIncluded" : false, "indexMin" : {"$numberLong" : "0"}, - "indexMax" : {"$numberLong" : "32"} + "indexMax" : {"$numberLong" : "32"}, + "trimFactor" : 0 }), .expectedError = "must be less than or equal to range max"}, {.description = "Int32 exclusive upper bound is 0", @@ -485,7 +680,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberInt" : "0"}, "ubIncluded" : false, "indexMin" : {"$numberInt" : "0"}, - "indexMax" : {"$numberInt" : "32"} + "indexMax" : {"$numberInt" : "32"}, + "trimFactor" : 0 }), .expectedError = "must be greater than the range minimum"}, {.description = "Double inclusive bounds", @@ -495,7 +691,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberDouble" : "35.25"}, "ubIncluded" : true, "indexMin" : {"$numberDouble" : "0"}, - "indexMax" : {"$numberDouble" : "1000"} + "indexMax" : {"$numberDouble" : "1000"}, + "trimFactor" : 0 }), .expectedMinCover = "11000000001101111\n" "1100000000111\n" @@ -511,7 +708,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberDouble" : "35.25"}, "ubIncluded" : false, "indexMin" : {"$numberDouble" : "0"}, - "indexMax" : {"$numberDouble" : "1000"} + "indexMax" : {"$numberDouble" : "1000"}, + "trimFactor" : 0 }), .expectedMinCover = "1100000000110111100000000000000000000000000000000000000000000001\n" "110000000011011110000000000000000000000000000000000000000000001\n" @@ -571,7 +769,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberDouble" : "35.25"}, "ubIncluded" : false, "indexMin" : {"$numberDouble" : "0"}, - "indexMax" : {"$numberDouble" : "1000"} + "indexMax" : {"$numberDouble" : "1000"}, + "trimFactor" : 0 }), .expectedMinCover = "11000000001101111\n" "1100000000111\n" @@ -585,7 +784,8 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te "upperBound" : {"$numberDouble" : "35.25"}, "ubIncluded" : true, "indexMin" : {"$numberDouble" : "0"}, - "indexMax" : {"$numberDouble" : "1000"} + "indexMax" : {"$numberDouble" : "1000"}, + "trimFactor" : 0 }), .expectedMinCover = "1100000000110111100000000000000000000000000000000000000000000001\n" "110000000011011110000000000000000000000000000000000000000000001\n" @@ -672,14 +872,22 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te ASSERT(bson_iter_init_find(&findSpecIter, findSpecDoc, "findSpec")); mc_FLE2RangeFindSpec_t findSpec; - ASSERT_OK_STATUS(mc_FLE2RangeFindSpec_parse(&findSpec, &findSpecIter, status), status); + bool res = mc_FLE2RangeFindSpec_parse(&findSpec, &findSpecIter, !test->disableRangeV2, status); + if (test->expectedErrorAtParseTime) { + ASSERT(!res); + ASSERT_STATUS_CONTAINS(status, test->expectedErrorAtParseTime); + goto cleanup; + } else { + ASSERT_OK_STATUS(res, status); + } size_t sparsity = 1; if (test->sparsity.set) { sparsity = (size_t)test->sparsity.value; } - mc_mincover_t *mc = mc_get_mincover_from_FLE2RangeFindSpec(&findSpec, sparsity, status); + const bool use_range_v2 = !test->disableRangeV2; + mc_mincover_t *mc = mc_get_mincover_from_FLE2RangeFindSpec(&findSpec, sparsity, status, use_range_v2); if (test->expectedError) { ASSERT(NULL == mc); @@ -690,13 +898,224 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te } mc_mincover_destroy(mc); + cleanup: bson_destroy(findSpecDoc); bson_destroy(findSpecVal); mongocrypt_status_destroy(status); } } +// Runs _mongocrypt_marking_to_ciphertext to compute the ciphertext for the given marking. +static void get_ciphertext_from_marking_json(_mongocrypt_tester_t *tester, + mongocrypt_t *crypt, + const char *markingJSON, + _mongocrypt_ciphertext_t *out) { + mongocrypt_status_t *status = mongocrypt_status_new(); + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + // Set up encryption environment + ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx); + // Add a test key + _mongocrypt_buffer_t keyId; + _mongocrypt_buffer_from_binary(&keyId, TEST_BIN(16)); + keyId.subtype = BSON_SUBTYPE_UUID; + _mongocrypt_key_broker_add_test_key(&ctx->kb, &keyId); + + _mongocrypt_buffer_t marking_buf; + _mongocrypt_marking_t marking; + bson_t *marking_bson = TMP_BSON(markingJSON); + // Add key identifier info to the marking + BSON_APPEND_BINARY(marking_bson, "ki", BSON_SUBTYPE_UUID, (TEST_BIN(16))->data, 16); + BSON_APPEND_BINARY(marking_bson, "ku", BSON_SUBTYPE_UUID, (TEST_BIN(16))->data, 16); + _make_marking(marking_bson, &marking_buf); + // Use FLE2 as the subtype (default is FLE1) + marking_buf.data[0] = MC_SUBTYPE_FLE2EncryptionPlaceholder; + _parse_ok(&marking_buf, &marking); + + ASSERT_OK_STATUS(_mongocrypt_marking_to_ciphertext((void *)&ctx->kb, &marking, out, status), status); + + mongocrypt_status_destroy(status); + _mongocrypt_buffer_cleanup(&marking_buf); + _mongocrypt_marking_cleanup(&marking); + mongocrypt_ctx_destroy(ctx); +} + +// Assert that the encryptedTokens fields in V2 insert/update ciphertext matches our expectations. Specifically, checks +// that the length of these fields are what we expect, and that the "isLeaf" token is appended when using range V2. +static void assert_correctness_of_ciphertext(_mongocrypt_ciphertext_t *ciphertext, + mongocrypt_t *crypt, + mc_ECOCToken_t *ecocToken, + bool useRangeV2, + uint32_t expectedEdges) { + uint32_t expectedPLength = useRangeV2 ? 33 : 32; + const _mongocrypt_value_encryption_algorithm_t *fle2alg = _mcFLE2Algorithm(); + mongocrypt_status_t *status = mongocrypt_status_new(); + + bson_t ciphertextBSON; + bson_iter_t iter; + ASSERT(_mongocrypt_buffer_to_bson(&ciphertext->data, &ciphertextBSON)); + + // 'p' field should be available, length should be 16 bytes of IV + expected bytes + bson_iter_init_find(&iter, &ciphertextBSON, "p"); + ASSERT(BSON_ITER_HOLDS_BINARY(&iter)); + uint32_t p_len; + const uint8_t *p_data; + bson_iter_binary(&iter, NULL, &p_len, &p_data); + ASSERT_CMPUINT32(p_len, ==, 16 + expectedPLength); + + if (useRangeV2) { + _mongocrypt_buffer_t p_buf, decrypted_buf; + ASSERT(_mongocrypt_buffer_copy_from_data_and_size(&p_buf, p_data, p_len)); + _mongocrypt_buffer_init_size(&decrypted_buf, expectedPLength); + uint32_t decryptedBytes; + // Decrypt p. When using range V2, last byte should be 0. + ASSERT_OK_STATUS(fle2alg->do_decrypt(crypt->crypto, + NULL, + mc_ECOCToken_get(ecocToken), + &p_buf, + &decrypted_buf, + &decryptedBytes, + status), + status); + ASSERT_CMPUINT32(decryptedBytes, ==, expectedPLength); + ASSERT_CMPUINT8(decrypted_buf.data[decrypted_buf.len - 1], ==, 0); + _mongocrypt_buffer_cleanup(&decrypted_buf); + _mongocrypt_buffer_cleanup(&p_buf); + } + + // 'g' field should be available + bson_iter_init_find(&iter, &ciphertextBSON, "g"); + ASSERT(BSON_ITER_HOLDS_ARRAY(&iter)); + uint32_t g_buf_len; + const uint8_t *g_buf; + bson_t g_arr; + bson_iter_array(&iter, &g_buf_len, &g_buf); + ASSERT(bson_init_static(&g_arr, g_buf, g_buf_len)); + + bson_iter_t g_iter; + bson_iter_init(&g_iter, &g_arr); + size_t g_count = 0, leaf_count = 0; + // Iterate through each edge token set and check p for each + while (bson_iter_next(&g_iter)) { + g_count++; + ASSERT(BSON_ITER_HOLDS_DOCUMENT(&g_iter)); + uint32_t subdoc_len; + const uint8_t *subdoc_buf; + bson_t subdoc; + bson_iter_document(&g_iter, &subdoc_len, &subdoc_buf); + ASSERT(bson_init_static(&subdoc, subdoc_buf, subdoc_len)); + + bson_iter_t sub_iter; + bson_iter_init_find(&sub_iter, &subdoc, "p"); + ASSERT(BSON_ITER_HOLDS_BINARY(&sub_iter)); + bson_iter_binary(&sub_iter, NULL, &p_len, &p_data); + ASSERT_CMPUINT32(p_len, ==, 16 + expectedPLength); + + if (useRangeV2) { + _mongocrypt_buffer_t p_buf, decrypted_buf; + ASSERT(_mongocrypt_buffer_copy_from_data_and_size(&p_buf, p_data, p_len)); + _mongocrypt_buffer_init_size(&decrypted_buf, expectedPLength); + + // Decrypt p. If useRangeV2, the last byte should be 0 or 1, depending on whether isLeaf. + uint32_t decrypted_bytes; + ASSERT_OK_STATUS(fle2alg->do_decrypt(crypt->crypto, + NULL, + mc_ECOCToken_get(ecocToken), + &p_buf, + &decrypted_buf, + &decrypted_bytes, + status), + status); + ASSERT_CMPUINT32(decrypted_bytes, ==, expectedPLength); + if (decrypted_buf.data[decrypted_buf.len - 1] == 1) { + leaf_count++; + } else { + ASSERT_CMPUINT8(decrypted_buf.data[decrypted_buf.len - 1], ==, 0) + } + + _mongocrypt_buffer_cleanup(&decrypted_buf); + _mongocrypt_buffer_cleanup(&p_buf); + } + } + ASSERT_CMPSIZE_T(g_count, ==, expectedEdges); + if (useRangeV2) { + // There should be exactly one leaf in any insert call. + ASSERT_CMPSIZE_T(leaf_count, ==, 1); + } + bson_destroy(&ciphertextBSON); + mongocrypt_status_destroy(status); +} + +// Get the ECOC token to use in decryption. +static mc_ECOCToken_t *getECOCToken(mongocrypt_t *crypt) { + mongocrypt_status_t *status = mongocrypt_status_new(); + // Test token key that we added earlier is all zeros. + _mongocrypt_buffer_t tokenKey; + _mongocrypt_buffer_init_size(&tokenKey, MONGOCRYPT_TOKEN_KEY_LEN); + memset(tokenKey.data, 0, MONGOCRYPT_TOKEN_KEY_LEN); + + mc_CollectionsLevel1Token_t *collectionsLevel1Token = + mc_CollectionsLevel1Token_new(crypt->crypto, &tokenKey, status); + mc_ECOCToken_t *ecocToken = mc_ECOCToken_new(crypt->crypto, collectionsLevel1Token, status); + ASSERT(mongocrypt_status_ok(status)); + + mc_CollectionsLevel1Token_destroy(collectionsLevel1Token); + _mongocrypt_buffer_cleanup(&tokenKey); + mongocrypt_status_destroy(status); + return ecocToken; +} + +static void test_mc_marking_to_ciphertext(_mongocrypt_tester_t *tester) { + if (!_aes_ctr_is_supported_by_os) { + printf("Common Crypto with no CTR support detected. Skipping."); + return; + } + + // Test that whether range V2 is enabled or disabled, the ciphertext matches our expectations. + { + const char markingJSON[] = RAW_STRING({ + 't' : 1, + 'a' : 3, + 'v' : {'min' : 0, 'max' : 7, 'v' : 5}, + 's' : {'$numberLong' : '1'}, + 'cm' : {'$numberLong' : '1'} + }); + _mongocrypt_ciphertext_t ciphertext; + _mongocrypt_ciphertext_init(&ciphertext); + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT); + + get_ciphertext_from_marking_json(tester, crypt, markingJSON, &ciphertext); + + mc_ECOCToken_t *ecocToken = getECOCToken(crypt); + assert_correctness_of_ciphertext(&ciphertext, crypt, ecocToken, false, 4); + _mongocrypt_ciphertext_cleanup(&ciphertext); + mc_ECOCToken_destroy(ecocToken); + mongocrypt_destroy(crypt); + } + { + const char markingJSON[] = RAW_STRING({ + 't' : 1, + 'a' : 3, + 'v' : {'min' : 0, 'max' : 7, 'v' : 5, 'trimFactor' : 0}, + 's' : {'$numberLong' : '1'}, + 'cm' : {'$numberLong' : '1'} + }); + _mongocrypt_ciphertext_t ciphertext; + _mongocrypt_ciphertext_init(&ciphertext); + mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_WITH_RANGE_V2); + + get_ciphertext_from_marking_json(tester, crypt, markingJSON, &ciphertext); + + mc_ECOCToken_t *ecocToken = getECOCToken(crypt); + assert_correctness_of_ciphertext(&ciphertext, crypt, ecocToken, true, 4); + _mongocrypt_ciphertext_cleanup(&ciphertext); + mc_ECOCToken_destroy(ecocToken); + + mongocrypt_destroy(crypt); + } +} + void _mongocrypt_tester_install_marking(_mongocrypt_tester_t *tester) { INSTALL_TEST(test_mongocrypt_marking_parse); INSTALL_TEST(test_mc_get_mincover_from_FLE2RangeFindSpec); + INSTALL_TEST(test_mc_marking_to_ciphertext); } diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-opts.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-opts.c new file mode 100644 index 0000000..4e98833 --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-opts.c @@ -0,0 +1,42 @@ +/* + * Copyright 2023-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 + +#include + +#define BSON_STR(...) #__VA_ARGS__ + +static void test_mongocrypt_opts_kms_providers_lookup(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *bson = TEST_BSON(BSON_STR({"azure" : {"accessToken" : "bar"}})); + + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, bson), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mc_kms_creds_t got; + ASSERT(_mongocrypt_opts_kms_providers_lookup(&crypt->opts.kms_providers, "azure", &got)); + ASSERT(got.type == MONGOCRYPT_KMS_PROVIDER_AZURE); + + ASSERT(!_mongocrypt_opts_kms_providers_lookup(&crypt->opts.kms_providers, "local", &got)); + ASSERT(got.type == MONGOCRYPT_KMS_PROVIDER_NONE); + + mongocrypt_destroy(crypt); +} + +void _mongocrypt_tester_install_opts(_mongocrypt_tester_t *tester) { + INSTALL_TEST(test_mongocrypt_opts_kms_providers_lookup); +} diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-traverse-util.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-traverse-util.c index 4774130..2f0e9f2 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-traverse-util.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-traverse-util.c @@ -101,7 +101,6 @@ static void _assert_correct_fields(bson_t *bson, int num_binary, int num_other, _util_tester_t *tester) { - char name[36]; bson_iter_t iter; bson_iter_t child; int i; @@ -112,34 +111,37 @@ static void _assert_correct_fields(bson_t *bson, BSON_ASSERT(num_binary < 10); BSON_ASSERT(num_other < 10); - memset(name, 0, 36); - if (tester->parent != NEST_IN_NONE) { for (i = 0; i < num_other; i++) { - snprintf(name, 13, "other.field%d", i); + char *key = bson_strdup_printf("other.field%d", i); bson_iter_init(&iter, bson); - BSON_ASSERT(bson_iter_find_descendant(&iter, name, &child)); + BSON_ASSERT(bson_iter_find_descendant(&iter, key, &child)); + bson_free(key); } for (i = 0; i < num_markings; i++) { - snprintf(name, 18, "markings.marking%d", i); + char *key = bson_strdup_printf("markings.marking%d", i); bson_iter_init(&iter, bson); - BSON_ASSERT(bson_iter_find_descendant(&iter, name, &child)); + BSON_ASSERT(bson_iter_find_descendant(&iter, key, &child)); + bson_free(key); } for (i = 0; i < num_random; i++) { - snprintf(name, 15, "random.random%d", i); + char *key = bson_strdup_printf("random.random%d", i); bson_iter_init(&iter, bson); - BSON_ASSERT(bson_iter_find_descendant(&iter, name, &child)); + BSON_ASSERT(bson_iter_find_descendant(&iter, key, &child)); + bson_free(key); } for (i = 0; i < num_deterministic; i++) { - snprintf(name, 29, "deterministic.deterministic%d", i); + char *key = bson_strdup_printf("deterministic.deterministic%d", i); bson_iter_init(&iter, bson); - BSON_ASSERT(bson_iter_find_descendant(&iter, name, &child)); + BSON_ASSERT(bson_iter_find_descendant(&iter, key, &child)); + bson_free(key); } for (i = 0; i < num_binary; i++) { - snprintf(name, 15, "binary.binary%d", i); + char *key = bson_strdup_printf("binary.binary%d", i); bson_iter_init(&iter, bson); - BSON_ASSERT(bson_iter_find_descendant(&iter, name, &child)); + BSON_ASSERT(bson_iter_find_descendant(&iter, key, &child)); + bson_free(key); } } else { @@ -155,7 +157,6 @@ static bson_t *_assemble_bson(int num_markings, int num_binary, int num_other, _util_tester_t *tester) { - char name[24]; bson_t *parent = NULL; bson_t bson; int i; @@ -167,8 +168,6 @@ static bson_t *_assemble_bson(int num_markings, BSON_ASSERT(num_binary < 10); BSON_ASSERT(num_other < 10); - memset(name, 0, 24); - /* If we have a nesting type, nest each kind of field inside one */ if (tester->parent == NEST_IN_DOCUMENT) { parent = bson_new(); @@ -182,45 +181,50 @@ static bson_t *_assemble_bson(int num_markings, /* Append some other filler fields */ for (i = 0; i < num_other; i++) { - snprintf(name, 7, "field%d", i); - BSON_ASSERT(bson_append_utf8(&bson, name, 6, "hi", -1)); + char *key = bson_strdup_printf("field%d", i); + BSON_ASSERT(bson_append_utf8(&bson, key, 6, "hi", -1)); + bson_free(key); } _reset_nesting(parent, &bson, tester->parent, "markings"); /* Append some number of markings */ for (i = 0; i < num_markings; i++) { - snprintf(name, 9, "marking%d", i); - _append_marking(&bson, name, 8); + char *key = bson_strdup_printf("marking%d", i); + _append_marking(&bson, key, 8); + bson_free(key); } _reset_nesting(parent, &bson, tester->parent, "random"); /* Append some number of random ciphertexts */ for (i = 0; i < num_random; i++) { - snprintf(name, 8, "random%d", i); - _append_ciphertext_with_subtype(&bson, name, 7, 6, MONGOCRYPT_ENCRYPTION_ALGORITHM_RANDOM, tester->tester); + char *key = bson_strdup_printf("random%d", i); + _append_ciphertext_with_subtype(&bson, key, 7, 6, MONGOCRYPT_ENCRYPTION_ALGORITHM_RANDOM, tester->tester); + bson_free(key); } _reset_nesting(parent, &bson, tester->parent, "deterministic"); /* Append some number of deterministic ciphertexts */ for (i = 0; i < num_deterministic; i++) { - snprintf(name, 15, "deterministic%d", i); + char *key = bson_strdup_printf("deterministic%d", i); _append_ciphertext_with_subtype(&bson, - name, + key, 14, 6, MONGOCRYPT_ENCRYPTION_ALGORITHM_DETERMINISTIC, tester->tester); + bson_free(key); } _reset_nesting(parent, &bson, tester->parent, "binary"); /* Append some number of other bson subtype 6 fields */ for (i = 0; i < num_binary; i++) { - snprintf(name, 8, "binary%d", i); - _append_ciphertext_with_subtype(&bson, name, 7, 5, MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE, tester->tester); + char *key = bson_strdup_printf("binary%d", i); + _append_ciphertext_with_subtype(&bson, key, 7, 5, MONGOCRYPT_ENCRYPTION_ALGORITHM_NONE, tester->tester); + bson_free(key); } if (tester->parent == NEST_IN_DOCUMENT) { diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.c index a4ccbf0..c5e5d89 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.c @@ -24,6 +24,7 @@ const char *mongocrypt_ctx_state_to_string(mongocrypt_ctx_state_t state) { switch (state) { case MONGOCRYPT_CTX_ERROR: return "MONGOCRYPT_CTX_ERROR"; + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: return "MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB"; case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: return "MONGOCRYPT_CTX_NEED_MONGO_COLLINFO"; case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: return "MONGOCRYPT_CTX_NEED_MONGO_MARKINGS"; case MONGOCRYPT_CTX_NEED_MONGO_KEYS: return "MONGOCRYPT_CTX_NEED_MONGO_KEYS"; @@ -70,6 +71,12 @@ bool kms_ctx_feed_all(mongocrypt_kms_ctx_t *kms_ctx, const uint8_t *data, uint32 while (mongocrypt_kms_ctx_bytes_needed(kms_ctx) > 0) { uint32_t len = mongocrypt_kms_ctx_bytes_needed(kms_ctx); + // Cap `len` to the total input length. + // `mongocrypt_kms_ctx_bytes_needed` may request more bytes than is in the response. + // The HTTP response parser defaults to requesting 1024 bytes initially. + if (len > datalen - offset) { + len = datalen - offset; + } ASSERT_CMPINT(offset + len, <=, datalen); bytes = mongocrypt_binary_new_from_data((uint8_t *)data + offset, len); if (!mongocrypt_kms_ctx_feed(kms_ctx, bytes)) { diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.h b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.h index e207dd6..0a5cda8 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.h +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.h @@ -31,6 +31,9 @@ char *data_to_hex(const uint8_t *data, size_t len); /* bson_iter_bson iterates a document or array into a bson_t. */ void bson_iter_bson(bson_iter_t *iter, bson_t *bson); +// `kms_ctx_feed_all` repeatedly calls `mongocrypt_kms_ctx_feed`. +// Returns false on a failed call to `mongocrypt_kms_ctx_feed`. +// Useful for KMIP. The KMIP response parser expects two calls: (length, then data). bool kms_ctx_feed_all(mongocrypt_kms_ctx_t *kms_ctx, const uint8_t *data, uint32_t datalen); #endif /* TEST_MONGOCRYPT_UTIL_H */ diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c index e5be392..7c6cde3 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c @@ -24,6 +24,7 @@ #include "mongocrypt-marking-private.h" #include "mongocrypt.h" #include "test-mongocrypt.h" +#include // kms_message_b64_pton #ifdef MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO #include @@ -268,7 +269,7 @@ void _mongocrypt_tester_satisfy_kms(_mongocrypt_tester_t *tester, mongocrypt_kms BSON_ASSERT(mongocrypt_kms_ctx_endpoint(kms, &endpoint)); BSON_ASSERT(endpoint == strstr(endpoint, "kms.") && strstr(endpoint, ".amazonaws.com")); - mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/example/kms-decrypt-reply.txt")); + mongocrypt_kms_ctx_feed(kms, TEST_FILE("./test/data/kms-aws/decrypt-response.txt")); BSON_ASSERT(0 == mongocrypt_kms_ctx_bytes_needed(kms)); } @@ -287,6 +288,7 @@ void _mongocrypt_tester_run_ctx_to(_mongocrypt_tester_t *tester, state = mongocrypt_ctx_state(ctx); while (state != stop_state) { switch (state) { + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: if (tester->paths.collection_info) { bin = TEST_FILE(tester->paths.collection_info); @@ -493,6 +495,11 @@ mongocrypt_t *_mongocrypt_tester_mongocrypt(tester_mongocrypt_flags flags) { if (flags & TESTER_MONGOCRYPT_WITH_CRYPT_SHARED_LIB) { mongocrypt_setopt_append_crypt_shared_lib_search_path(crypt, "$ORIGIN"); } + if (flags & TESTER_MONGOCRYPT_WITH_RANGE_V2) { + ASSERT(mongocrypt_setopt_use_range_v2(crypt)); + } else { + crypt->opts.use_range_v2 = false; + } ASSERT_OK(mongocrypt_init(crypt), crypt); if (flags & TESTER_MONGOCRYPT_WITH_CRYPT_SHARED_LIB) { if (mongocrypt_crypt_shared_lib_version(crypt) == 0) { @@ -504,6 +511,15 @@ mongocrypt_t *_mongocrypt_tester_mongocrypt(tester_mongocrypt_flags flags) { return crypt; } +bool _mongocrypt_init_for_test(mongocrypt_t *crypt) { + BSON_ASSERT_PARAM(crypt); + // Even if the ENABLE_USE_RANGE_V2 compile flag is on, we should have range V2 off by default for testing, as many + // existing tests are based around range V2 being disabled. To use range V2, use the TESTER_MONGOCRYPT_WITH_RANGE_V2 + // flag with the above function. + crypt->opts.use_range_v2 = false; + return mongocrypt_init(crypt); +} + static void _test_mongocrypt_bad_init(_mongocrypt_tester_t *tester) { mongocrypt_t *crypt; mongocrypt_binary_t *local_key; @@ -511,7 +527,7 @@ static void _test_mongocrypt_bad_init(_mongocrypt_tester_t *tester) { /* Omitting a KMS provider must fail. */ crypt = mongocrypt_new(); - ASSERT_FAILS(mongocrypt_init(crypt), crypt, "no kms provider set"); + ASSERT_FAILS(_mongocrypt_init_for_test(crypt), crypt, "no kms provider set"); mongocrypt_destroy(crypt); /* Bad KMS provider options must fail. */ @@ -549,13 +565,13 @@ static void _test_mongocrypt_bad_init(_mongocrypt_tester_t *tester) { /* Reinitialization must fail. */ crypt = mongocrypt_new(); ASSERT_OK(mongocrypt_setopt_kms_provider_aws(crypt, "example", -1, "example", -1), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); - ASSERT_FAILS(mongocrypt_init(crypt), crypt, "already initialized"); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + ASSERT_FAILS(_mongocrypt_init_for_test(crypt), crypt, "already initialized"); mongocrypt_destroy(crypt); /* Setting options after initialization must fail. */ crypt = mongocrypt_new(); ASSERT_OK(mongocrypt_setopt_kms_provider_aws(crypt, "example", -1, "example", -1), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ASSERT_FAILS(mongocrypt_setopt_kms_provider_aws(crypt, "example", -1, "example", -1), crypt, "options cannot be set after initialization"); @@ -599,7 +615,7 @@ static void _test_setopt_encrypted_field_config_map(_mongocrypt_tester_t *tester ASSERT_OK( mongocrypt_setopt_encrypted_field_config_map(crypt, TEST_FILE("./test/data/encrypted-field-config-map.json")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); mongocrypt_destroy(crypt); /* Test double setting. */ @@ -640,7 +656,7 @@ static void _test_setopt_encrypted_field_config_map(_mongocrypt_tester_t *tester ASSERT_OK( mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'bar'}}")), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); mongocrypt_destroy(crypt); /* Test that it is an error to set both the encrypted field config map and @@ -652,7 +668,7 @@ static void _test_setopt_encrypted_field_config_map(_mongocrypt_tester_t *tester ASSERT_OK( mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{'aws': {'accessKeyId': 'foo', 'secretAccessKey': 'bar'}}")), crypt); - ASSERT_FAILS(mongocrypt_init(crypt), + ASSERT_FAILS(_mongocrypt_init_for_test(crypt), crypt, "db.coll1 is present in both schema_map and encrypted_field_config_map"); mongocrypt_destroy(crypt); @@ -665,7 +681,7 @@ static void _test_setopt_invalid_kms_providers(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); ASSERT_OK(mongocrypt_setopt_kms_provider_aws(crypt, "", 0, "", 0), crypt); - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); ctx = mongocrypt_ctx_new(crypt); ASSERT_OK(mongocrypt_ctx_setopt_masterkey_aws(ctx, "region", -1, "cmk", 3), ctx); @@ -683,7 +699,7 @@ static void _test_setopt_invalid_kms_providers(_mongocrypt_tester_t *tester) { crypt = mongocrypt_new(); mongocrypt_setopt_use_need_kms_credentials_state(crypt); ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON("{}")), crypt); - ASSERT_FAILS(mongocrypt_init(crypt), crypt, "no kms provider set"); + ASSERT_FAILS(_mongocrypt_init_for_test(crypt), crypt, "no kms provider set"); mongocrypt_destroy(crypt); } @@ -725,7 +741,7 @@ static void _test_setopt_kms_providers(_mongocrypt_tester_t *tester) { "'privateKey': {'$binary': {'base64': 'AAAA', 'subType': '00'}} }}"}, /* endpoint is not required. */ {"{'gcp': {'email': 'test', 'privateKey': 'AAAA' }}"}, - {"{'gcp': {'privateKey': 'AAAA'}}", "expected UTF-8 gcp.email"}, + {"{'gcp': {'privateKey': 'AAAA'}}", "Failed to parse KMS provider `gcp`: expected UTF-8 email"}, {"{'gcp': {'email': 'test', 'privateKey': 'invalid base64' }}", "unable to parse base64"}, {"{'gcp': {'endpoint': 'example', 'email': 'test', 'privateKey': " "'AAAA'}}", @@ -776,15 +792,46 @@ static void _test_setopt_kms_providers(_mongocrypt_tester_t *tester) { if (!test->errmsg) { ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, TEST_BSON(test->value)), crypt); if (!test->errmsg_init) { - ASSERT_OK(mongocrypt_init(crypt), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); } else { - ASSERT_FAILS(mongocrypt_init(crypt), crypt, test->errmsg_init); + ASSERT_FAILS(_mongocrypt_init_for_test(crypt), crypt, test->errmsg_init); } } else { ASSERT_FAILS(mongocrypt_setopt_kms_providers(crypt, TEST_BSON(test->value)), crypt, test->errmsg); } mongocrypt_destroy(crypt); } + + // Errors if followed by call to `mongocrypt_setopt_kms_providers` configuring "local". + // This is a regression test for: MONGOCRYPT-610 + { + _mongocrypt_buffer_t local_kek_buf; + // Create buffer for local KEK to pass data. + { + _mongocrypt_buffer_init(&local_kek_buf); + _mongocrypt_buffer_resize(&local_kek_buf, MONGOCRYPT_KEY_LEN); + int result_len = + kms_message_b64_pton(EXAMPLE_LOCAL_MATERIAL, local_kek_buf.data, (size_t)local_kek_buf.len); + ASSERT_CMPINT(result_len, ==, MONGOCRYPT_KEY_LEN); + } + + mongocrypt_binary_t *more = TEST_BSON("{'local' : {'key' : '%s'}}", EXAMPLE_LOCAL_MATERIAL); + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_provider_local(crypt, _mongocrypt_buffer_as_binary(&local_kek_buf)), crypt); + ASSERT_FAILS(mongocrypt_setopt_kms_providers(crypt, more), crypt, "already set"); + mongocrypt_destroy(crypt); + _mongocrypt_buffer_cleanup(&local_kek_buf); + } + + // Errors if followed by call to `mongocrypt_setopt_kms_providers` configuring "aws". + // This is a regression test for: MONGOCRYPT-610 + { + mongocrypt_binary_t *more = TEST_BSON("{'aws' : {'accessKeyId' : 'foo', 'secretAccessKey' : 'bar'}}"); + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_provider_aws(crypt, "foo", -1, "bar", -1), crypt); + ASSERT_FAILS(mongocrypt_setopt_kms_providers(crypt, more), crypt, "already set"); + mongocrypt_destroy(crypt); + } } bool _aes_ctr_is_supported_by_os = true; @@ -837,6 +884,7 @@ int main(int argc, char **argv) { _mongocrypt_tester_install_fle2_payloads(&tester); _mongocrypt_tester_install_fle2_iev_v2_payloads(&tester); _mongocrypt_tester_install_efc(&tester); + _mongocrypt_tester_install_cleanup(&tester); _mongocrypt_tester_install_compact(&tester); _mongocrypt_tester_install_fle2_payload_uev(&tester); _mongocrypt_tester_install_fle2_payload_uev_v2(&tester); @@ -852,6 +900,8 @@ int main(int argc, char **argv) { _mongocrypt_tester_install_gcp_auth(&tester); _mongocrypt_tester_install_mc_reader(&tester); _mongocrypt_tester_install_mc_writer(&tester); + _mongocrypt_tester_install_opts(&tester); + _mongocrypt_tester_install_named_kms_providers(&tester); #ifdef MONGOCRYPT_ENABLE_CRYPTO_COMMON_CRYPTO char osversion[32]; @@ -937,8 +987,10 @@ void _test_ctx_wrap_and_feed_key(mongocrypt_ctx_t *ctx, const _mongocrypt_buffer_t *id, _mongocrypt_buffer_t *key, mongocrypt_status_t *status) { + mc_kms_creds_t kc; + ASSERT(_mongocrypt_opts_kms_providers_lookup(_mongocrypt_ctx_kms_providers(ctx), "local", &kc)); // Wrap key using local provider. - _mongocrypt_buffer_t kek = _mongocrypt_ctx_kms_providers(ctx)->local.key; + _mongocrypt_buffer_t kek = kc.value.local.key; _mongocrypt_buffer_t encrypted_key; _mongocrypt_buffer_init(&encrypted_key); ASSERT_OK_STATUS(_mongocrypt_wrap_key(ctx->crypt->crypto, &kek, key, &encrypted_key, status), status); diff --git a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h index 25d2717..b4950ca 100644 --- a/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h +++ b/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h @@ -42,6 +42,8 @@ typedef enum tester_mongocrypt_flags { TESTER_MONGOCRYPT_WITH_CRYPT_SHARED_LIB = 1 << 0, /// Enable wire protocol version v1 TESTER_MONGOCRYPT_WITH_CRYPT_V1 = 1 << 1, + /// Enable range V2 + TESTER_MONGOCRYPT_WITH_RANGE_V2 = 1 << 2, } tester_mongocrypt_flags; /* Arbitrary max of 2048 instances of temporary test data. Increase as needed. @@ -96,6 +98,9 @@ void _mongocrypt_tester_fill_buffer(_mongocrypt_buffer_t *buf, int n); /* Return a new initialized mongocrypt_t for testing. */ mongocrypt_t *_mongocrypt_tester_mongocrypt(tester_mongocrypt_flags options); +/* Initialize a new mongocrypt_t for use in testing. */ +bool _mongocrypt_init_for_test(mongocrypt_t *); + typedef enum { CRYPTO_REQUIRED, CRYPTO_OPTIONAL, CRYPTO_PROHIBITED } _mongocrypt_tester_crypto_spec_t; void _mongocrypt_tester_install(_mongocrypt_tester_t *tester, @@ -165,6 +170,8 @@ void _mongocrypt_tester_install_fle2_iev_v2_payloads(_mongocrypt_tester_t *teste void _mongocrypt_tester_install_efc(_mongocrypt_tester_t *tester); +void _mongocrypt_tester_install_cleanup(_mongocrypt_tester_t *tester); + void _mongocrypt_tester_install_compact(_mongocrypt_tester_t *tester); void _mongocrypt_tester_install_fle2_payload_uev(_mongocrypt_tester_t *tester); @@ -195,6 +202,10 @@ void _mongocrypt_tester_install_mc_reader(_mongocrypt_tester_t *tester); void _mongocrypt_tester_install_mc_writer(_mongocrypt_tester_t *tester); +void _mongocrypt_tester_install_opts(_mongocrypt_tester_t *tester); + +void _mongocrypt_tester_install_named_kms_providers(_mongocrypt_tester_t *tester); + /* Conveniences for getting test data. */ /* Get a temporary bson_t from a JSON string. Do not free it. */ diff --git a/ext/libmongocrypt/libmongocrypt/test/test-named-kms-providers.c b/ext/libmongocrypt/libmongocrypt/test/test-named-kms-providers.c new file mode 100644 index 0000000..ea5727a --- /dev/null +++ b/ext/libmongocrypt/libmongocrypt/test/test-named-kms-providers.c @@ -0,0 +1,2381 @@ +/* + * Copyright 2023-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 + +#include +#include + +#define LOCAL_KEK1_BASE64 \ + "+ol0TFyLuVvKFSqGzOFGuaOGQnnyfAqalhOv3II/VSxQTCORCGhOmw/IxhthGx0r" \ + "2R/NpMWc91qQ8Ieho4QuE9ucToTnpJ4OquFpdZv2IcO4gey3ecZGCl9jPDig8F+a" + +#define LOCAL_KEK2_BASE64 \ + "yPSpsO8FoVkmt+qdTDnw/pJaKriwfI6NLD1yse3BZLd3ZcXb3rAVJEA+/yu/vPzE" \ + "8ju7OYTV63AwfLor8Hg9qzo8lyYC6H3RSfdJ9g9aXdCRfGZJgpbpchJUjR06JMLR" + +// clang-format off +// GCP_PRIVATEKEY1 was generated with: `openssl genrsa -out private-key.pem 2048` +#define GCP_PRIVATEKEY1 "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCaqoCoH23dVS8see2DPOpHF3VHtKrXED2zcTkr+C15dDsw3hEl7123xwby/nSg08TMN9uzWkTaIP/CRNhN/VO3dmlCoRy/1Tyx8r3P7mELNPv7X6FP3MgcRMwSesvp7RYnTsImxQ6c48yTd2a4KnjFkJ9HkbOdxjoK2FENwPMdKNgU66XdzqIJBTeqSmx4FuTKdjQm3wi6vHYZgkZ1CKn90oDzpUwwIk3O4614Hxw8Gq40HgpwuTxKLFmfEgqyTHn54pw7plVivwwaUE2tXv3T4TIb0C8J9qquRtWSJuBVBM7yNucsNuWIXzW9jOT6PGcK30OIpkmf6n0Ib2pgY+WhAgMBAAECggEADypgDGwtg4YEZsPrX0KYNcGV90KevFEMPcXAvYAbpGS6X5WswIeerMQkGSxMbw8oxT4GackUhn91GJ1TyNzpyivfESCXXzOHXKsAw+xbwWOwABNdz8UGLahsyrSV/VFpKlBJjw/kOYvILd8HuE/40OV4CsZdgn9TBmh01SiJ5h5JtRP+kZycYluiUo0zLBReI8bpFPnWlCBDJJPE+UpFUCcifw/2xTkACJChtLmDDJ3NkUYACWQZ8HDf3UG3yE+OAGtP27srn1DYs6aNsr/dGfVU6Lu1mO8HswlSm4XHckdVdEmPaj/g5+TGBidnli8yMOhaPk5oDyD0DSltz4Ss2QKBgQDQ8xkFOCPQxnj6eO0s/8SXfoLQyCpHLqXNF7rw5H6VHo+5iyOt146XeLJNQeTYi/JX6bAlyPfc51ESZsjG1NucyLToJf7+Q+o/w/dNq3eNvGH1rxfYdalD4woQL+JQcgnelnMInyTCPS7drXbugl2AH2JzbwwyBHMB5KeW9paXSQKBgQC9fjo9G/ULae+w27aGSOYCnaFb0LlOJ5merjaZF3GkZPE3RhGIY19C2HRcjre4qRZbrPqyLkF8hoiLMTEd+n+vn8jUQaw/A67tVS1egnJlhut8BcFxW/jhmE80fIzRfxtRQhB/mevxTAIhhLUks3I7CZAjUabx9F+RAYLg3ZCjmQKBgBaj0Hk1TQQpDSCui5xNlkKH7aqrlZEi58oiIRpK18BWkGIdRl9mtMeKx18Bnccs2rRV2MUvUlP4KFujEWwh0i3ZvWhN/aQVPcNs+1XKF2kfGUoij6XfkdiOOB/q4E2xHYqlqI8tlzEIqhRQ4EsViwX/4I37YUnmG4P//3ym+UgpAoGAUMAx4UjArBSA6EU5CxCVtBeoY5AW549Ij6595c9vxjad9IgPgKeYOMw1ChxnfnHP7VFRpAzCK2bJWUelPrk5IIZe9tTlqhTPvqPFqbi9Nza/syJgxQYEkV5uoldRSxV3drFIhpf5S+KwJch/yRwPWclBe0uYcRNKhmi2dUz2DkECgYB4MazvGlNzdAGGt9ah+Ytq0ZZLaJlZMjlNZdsmiWn3Lhxy/l3ibTb1vALo7rQoH3Fpb55B+aiEPMtWVx0yVeIBaHmxQ+Q1Qes8vkL0ONAc4ZUPN9IVu2l8TE+cM6qzoZjpJMwK/JiFmqkE/Gss7gBgCr5JEQrXj2VecBSAcZXMwA==" +// GCP_PRIVATEKEY2 was generated with: `openssl genrsa -out private-key.pem 2048` +#define GCP_PRIVATEKEY2 "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC4OWLdpC6AKXjskPiMa/oomIlT5RqeDvcDjQBKyhBTJ8cj3brB4xTBYVNAjBuHZeD8hKGs+6m4PPBxFEt5i7dPZNQZzDJ8Gk4xEkL4Ukgzx1rYwAI1f/Ef45gqUGZJC/kSCAUoGG5FUr+o23W6OCrx302ZVPGB+MbvO6cuTv6DlpHw3w9djpy4l6aMlj+JFCKnR7ai9yoAia8IYa0edMPi2HxdQZziHdlkw3wp+jBvN/706a24TzZKa1ewz2K2lQlc8G2iLy9+AcbHwYKo07ETKmu5azOr4yJ47aC2+SnXQzSFmDOJVTAq8/PXNQVscialqOdwMVpnWE5AFw/DxJibAgMBAAECgf9IZdgVXa7+XTg7lEWWkpdCZ9Xcdu44JJOiVwtcInRCexBzRoy5qv6w3+iIzzUzZXbyihHOhKCNkzm5uX6z1er1nP7OCV5xIEdpSEll60dUDH7gc6UurX3b/MPCauwT5CCphb63gyO9BNWkfk5Qt7HGyQ3/bVo/8u7TqJsYeeKA9B5j6LrnW/gITJGOSzq9j3PpWTMGbi0T57tMBZhRmncZ4jfDruXvPsZlXFnV2sfbtgCzpaOfAQ/CKa5PHz382b7sitEoKuwtYVBrTxLKTTUhRneGaK47lhBFsbEtqhicVYOUfplgE/wLrhmFcjRkmxAzPYq89QfaQ60LGiBrMUUCgYEA5NrMJgvife4DdhtFR2yiN3ufXJtqvMUtfZZAZoPD7fVz0VSwYEfkhuNCtt0U6CD3xjpWFOL372YycNI+apyhL3kL2Jnrpsh5mjjCnLoFqKVVgTWK9GFNSzVeO9LNjGJpR1nZDorZ2FHeUW4SAfMs5b1wek7xAnPrNHYEE8TgRx8CgYEAzhNgl++WWvj/pLKwLc/Gxz03rOoXYPnAnsfyO4g9F883Ps9uVgTro9EKeD9n+nPRbSRISZExe5P8EVUXrIpviO3oHE7fvdzoBfr2Vf5c/qQ0anD47RJODjJyKwrkuWxkxotPDWU/msZdyO7hf3v5BxevrP0Bzg2+zmbVE3dvKwUCgYEAt+Gdusw91hVSLqnGxpbg2Fe6OjyeTMLZxFjfsf8ZhK99uaqkdRgO5NrhlfCZhdJHg70HwYyEzpR83u3vPNZRJMXL4OP71myqWGJW7HsDZPhDdahB2A3+fvmIl+TPR4cjNDNbFjY2x3sweJlKWsq7PnUyVPPs7p2ZVPOmXwQHeN0CgYATslZxLz03xMTqgQnF1y4wrPE9XcKOSlDW3FWSyxrLw8qL/leVcTL0nW5av/S4Q4mo3Obr4SzRmvtkzLVOkIzIkbS1v/QyuYKTz8DrxzwsOpWn9tRUFIPRZ5Dx/ECQWIPpVjdgGGVT7dHY+rwi6z6KJwFrj2M0xquOHtYO3kOJ4QKBgQDDHjZTAyzMVWJiUDI6ENSKqTUDQh/UxI1zpMxp9qoHUwO8iHF4BLastquvK/sUuRbF6mI6z9/theDEqzP5Ytd5YrD2QOBJQhX8NDmO575+N7AldsxupVqjJWrivWo/cJMOwhLZ+OHLJjkfrZQSDjg70gS7AsFeLweLO3Aa9thVYw==" +// clang-format on + +#define BSON_STR(...) #__VA_ARGS__ + +// `kmip_get_operation_type` returns a string representation of an Operation in a KMIP request. +// Useful for tests wanting to assert the type of KMIP request contained in a `mongocrypt_kms_ctx_t`. +static const char *kmip_get_operation_type(mongocrypt_binary_t *bin) { + // Convert to hex for easier searching with `strstr`. + char *as_hex = data_to_hex(mongocrypt_binary_data(bin), mongocrypt_binary_len(bin)); + const char *needle = "42005c" // Tag=Operation + "05" // Type=Enum + "00000004" // Length + "000000"; // First three bytes of four byte value. + char *found = strstr(as_hex, needle); + if (!found) { + bson_free(as_hex); + return "Not found"; + } + // Read the next two hex characters. + found += strlen(needle); + const char *got = "Unknown"; + // Refer to section 9.1.3.2.26 of KMIP 1.0 specification for the Operation values. + if (0 == strncmp(found, "01", 2)) { + got = "Create"; + } else if (0 == strncmp(found, "02", 2)) { + got = "Create_Key_Pair"; + } else if (0 == strncmp(found, "03", 2)) { + got = "Register"; + } else if (0 == strncmp(found, "04", 2)) { + got = "Rekey"; + } else if (0 == strncmp(found, "05", 2)) { + got = "Derive_Key"; + } else if (0 == strncmp(found, "06", 2)) { + got = "Certify"; + } else if (0 == strncmp(found, "07", 2)) { + got = "Recertify"; + } else if (0 == strncmp(found, "08", 2)) { + got = "Locate"; + } else if (0 == strncmp(found, "09", 2)) { + got = "Check"; + } else if (0 == strncmp(found, "0a", 2)) { + got = "Get"; + } else if (0 == strncmp(found, "0b", 2)) { + got = "Get_Attributes"; + } else if (0 == strncmp(found, "0c", 2)) { + got = "Get_Attribute_List"; + } else if (0 == strncmp(found, "0d", 2)) { + got = "Add_Attribute"; + } else if (0 == strncmp(found, "0e", 2)) { + got = "Modify_Attribute"; + } else if (0 == strncmp(found, "0f", 2)) { + got = "Delete_Attribute"; + } else if (0 == strncmp(found, "10", 2)) { + got = "Obtain_Lease"; + } else if (0 == strncmp(found, "11", 2)) { + got = "Get_Usage_Allocation"; + } else if (0 == strncmp(found, "12", 2)) { + got = "Activate"; + } else if (0 == strncmp(found, "13", 2)) { + got = "Revoke"; + } else if (0 == strncmp(found, "14", 2)) { + got = "Destroy"; + } else if (0 == strncmp(found, "15", 2)) { + got = "Archive"; + } else if (0 == strncmp(found, "16", 2)) { + got = "Recover"; + } else if (0 == strncmp(found, "17", 2)) { + got = "Validate"; + } else if (0 == strncmp(found, "18", 2)) { + got = "Query"; + } else if (0 == strncmp(found, "19", 2)) { + got = "Cancel"; + } else if (0 == strncmp(found, "1a", 2)) { + got = "Poll"; + } else if (0 == strncmp(found, "1b", 2)) { + got = "Notify"; + } else if (0 == strncmp(found, "1c", 2)) { + got = "Put"; + } + bson_free(as_hex); + return got; +} + +/* +clang-format off + +`KMIP_REGISTER_RESPONSE` represents: + + + + + + + + + + + + + + + + + + + +clang-format on +*/ +static const uint8_t KMIP_REGISTER_RESPONSE[] = { + 0x42, 0x00, 0x7b, 0x01, 0x00, 0x00, 0x00, 0x90, 0x42, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x00, 0x48, 0x42, 0x00, 0x69, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x65, 0x82, 0xec, 0x0b, 0x42, 0x00, 0x0d, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x00, + 0x38, 0x42, 0x00, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x7c, 0x01, 0x00, + 0x00, 0x00, 0x10, 0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x02, 0x31, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* +clang-format off + +`KMIP_ACTIVATE_RESPONSE` represents: + + + + + + + + + + + + + + + + + + + +clang-format on +*/ +static const uint8_t KMIP_ACTIVATE_RESPONSE[] = { + 0x42, 0x00, 0x7b, 0x01, 0x00, 0x00, 0x00, 0x90, 0x42, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x00, 0x48, 0x42, 0x00, 0x69, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x65, 0x82, 0xec, 0x0b, 0x42, 0x00, 0x0d, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x00, + 0x38, 0x42, 0x00, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x7c, 0x01, 0x00, + 0x00, 0x00, 0x10, 0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x02, 0x31, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* +clang-format off + +`KMIP_GET_RESPONSE` represents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +clang-format on +*/ +static const uint8_t KMIP_GET_RESPONSE[] = { + 0x42, 0x00, 0x7b, 0x01, 0x00, 0x00, 0x01, 0x40, 0x42, 0x00, 0x7a, 0x01, 0x00, 0x00, 0x00, 0x48, 0x42, 0x00, 0x69, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x00, 0x92, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x65, 0x82, 0xec, 0x0b, 0x42, 0x00, 0x0d, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x00, + 0xe8, 0x42, 0x00, 0x5c, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x7c, 0x01, 0x00, + 0x00, 0x00, 0xc0, 0x42, 0x00, 0x57, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x00, 0x94, 0x07, 0x00, 0x00, 0x00, 0x02, 0x31, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x85, + 0x01, 0x00, 0x00, 0x00, 0x98, 0x42, 0x00, 0x86, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x80, 0x42, 0x00, 0x42, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x68, 0x42, 0x00, 0x43, 0x08, + 0x00, 0x00, 0x00, 0x60, 0xe6, 0xe4, 0xb2, 0x50, 0x4f, 0xc6, 0x1c, 0x4e, 0x8e, 0x45, 0x69, 0x1b, 0x17, 0x19, 0xd5, + 0xd6, 0x61, 0x8b, 0x74, 0x91, 0x67, 0x10, 0x06, 0x83, 0xf4, 0xf8, 0xe5, 0x5d, 0xf1, 0xf2, 0x2a, 0xd3, 0xcb, 0xba, + 0x2a, 0xb4, 0x21, 0xed, 0x9d, 0xae, 0xb7, 0x3b, 0xc2, 0x5c, 0x03, 0x1a, 0xde, 0x82, 0x05, 0x80, 0xa5, 0xc7, 0x55, + 0x18, 0xab, 0x21, 0x37, 0x9b, 0x39, 0x36, 0xef, 0xfb, 0xcf, 0xcd, 0xa1, 0x46, 0xb2, 0x16, 0x71, 0xf2, 0xcf, 0x9f, + 0x80, 0x12, 0xb0, 0xe1, 0x83, 0xd7, 0x19, 0x16, 0x64, 0x81, 0x07, 0x5d, 0x6c, 0x39, 0x32, 0xa5, 0xae, 0xd5, 0x41, + 0x1f, 0x0c, 0x26, 0xe1, 0x57}; + +static void test_configuring_named_kms_providers(_mongocrypt_tester_t *tester) { + // Test that a named KMS provider can be set. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"local" : {"key" : "%s"}, "local:name1" : {"key" : "%s"}}), + LOCAL_KEK1_BASE64, + LOCAL_KEK2_BASE64); + bool ok = mongocrypt_setopt_kms_providers(crypt, kms_providers); + ASSERT_OK(ok, crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + mongocrypt_destroy(crypt); + } + + // Test that an unrecognized named KMS provider errors. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({"foo:bar" : {"key" : "%s"}}), LOCAL_KEK1_BASE64); + bool ok = mongocrypt_setopt_kms_providers(crypt, kms_providers); + ASSERT_FAILS(ok, crypt, "unrecognized type"); + mongocrypt_destroy(crypt); + } + + // Test character validation. Only valid characters are: [a-zA-Z0-9_] + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"local:name_with_invalid_character_?" : {"key" : "%s"}}), LOCAL_KEK1_BASE64); + bool ok = mongocrypt_setopt_kms_providers(crypt, kms_providers); + ASSERT_FAILS(ok, crypt, "unsupported character `?`"); + mongocrypt_destroy(crypt); + } + + // Test configuring a named KMS provider with an empty document is prohibited. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({"local:name1" : {}})); + bool ok = mongocrypt_setopt_kms_providers(crypt, kms_providers); + ASSERT_FAILS(ok, crypt, "Unexpected empty document for named KMS provider"); + mongocrypt_destroy(crypt); + + // An empty document is allowed for a non-named KMS provider to configure on-demand credentials. + crypt = mongocrypt_new(); + kms_providers = TEST_BSON(BSON_STR({"local" : {}})); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + mongocrypt_destroy(crypt); + } + + // Test that duplicate named KMS providers is an error. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"local:name1" : {"key" : "%s"}, "local:name1" : {"key" : "%s"}}), + LOCAL_KEK1_BASE64, + LOCAL_KEK2_BASE64); + ASSERT_FAILS(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt, "duplicate entry"); + mongocrypt_destroy(crypt); + } + + // Test that a named KMS provider can be set with Azure. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({ + "local" : {"key" : "%s"}, + "azure:name1" : { + "tenantId" : "placeholder1-tenantId", + "clientId" : "placeholder1-clientId", + "clientSecret" : "placeholder1-clientSecret", + "identityPlatformEndpoint" : "placeholder1-identityPlatformEndpoint.com" + } + }), + LOCAL_KEK1_BASE64); + bool ok = mongocrypt_setopt_kms_providers(crypt, kms_providers); + ASSERT_OK(ok, crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + mongocrypt_destroy(crypt); + } + + // Test that only configuring named KMS provider is OK. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({"local:name1" : {"key" : "%s"}}), LOCAL_KEK1_BASE64); + bool ok = mongocrypt_setopt_kms_providers(crypt, kms_providers); + ASSERT_OK(ok, crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + mongocrypt_destroy(crypt); + } + + // Test configuring with an empty name is an error. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({"local:" : {"key" : "%s"}}), LOCAL_KEK1_BASE64); + ASSERT_FAILS(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt, "empty name"); + mongocrypt_destroy(crypt); + } +} + +static void test_create_datakey_with_named_kms_provider(_mongocrypt_tester_t *tester) { + // Test creating with an unconfigured KMS provider. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({"local:name1" : {"key" : "%s"}}), LOCAL_KEK1_BASE64); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create with named KMS provider. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK( + mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({"provider" : "local:not_configured"}))), + ctx); + ASSERT_FAILS(mongocrypt_ctx_datakey_init(ctx), + ctx, + "requested kms provider not configured: `local:not_configured`"); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test creating with an unconfigured KMS provider, when provider of same type is configured. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"local" : {"key" : "%s"}, "local:name1" : {"key" : "%s"}}), + LOCAL_KEK1_BASE64, + LOCAL_KEK2_BASE64); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create with named KMS provider. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK( + mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({"provider" : "local:not_configured"}))), + ctx); + ASSERT_FAILS(mongocrypt_ctx_datakey_init(ctx), + ctx, + "requested kms provider not configured: `local:not_configured`"); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test creating with an unconfigured KMS provider, when provider of same type is configured with an + // empty document. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"local" : {}, "local:name1" : {"key" : "%s"}}), LOCAL_KEK1_BASE64, LOCAL_KEK2_BASE64); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + mongocrypt_setopt_use_need_kms_credentials_state(crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create with named KMS provider. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK( + mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({"provider" : "local:not_configured"}))), + ctx); + ASSERT_FAILS(mongocrypt_ctx_datakey_init(ctx), + ctx, + "requested kms provider required by datakey is not configured: `local:not_configured`"); + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test successfully creating a local DEK with a named KMS provider. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({"local:name1" : {"key" : "%s"}}), LOCAL_KEK1_BASE64); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create with named KMS provider. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({"provider" : "local:name1"}))), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + // Check that `out` contains name. + bson_t out_bson; + ASSERT(_mongocrypt_binary_to_bson(out, &out_bson)); + char *pattern = BSON_STR({"masterKey" : {"provider" : "local:name1"}}); + _assert_match_bson(&out_bson, TMP_BSON(pattern)); + bson_destroy(&out_bson); + mongocrypt_binary_destroy(out); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test successfully creating an Azure DEK with a named KMS provider + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({ + "azure:name1" : { + "tenantId" : "placeholder1-tenantId", + "clientId" : "placeholder1-clientId", + "clientSecret" : "placeholder1-clientSecret", + "identityPlatformEndpoint" : "placeholder1-identityPlatformEndpoint.com" + } + })); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create with named KMS provider. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({ + "provider" : "azure:name1", + "keyName" : "placeholder1-keyName", + "keyVaultEndpoint" : "placeholder1-keyVaultEndpoint.com" + }))), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to encrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/encrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + // Check that `out` contains name. + bson_t out_bson; + ASSERT(_mongocrypt_binary_to_bson(out, &out_bson)); + char *pattern = BSON_STR({"masterKey" : {"provider" : "azure:name1"}}); + _assert_match_bson(&out_bson, TMP_BSON(pattern)); + bson_destroy(&out_bson); + mongocrypt_binary_destroy(out); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test successfully creating an Azure DEK when `accessToken` is passed. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({"azure:name1" : {"accessToken" : "foo"}})); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create with named KMS provider. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({ + "provider" : "azure:name1", + "keyName" : "placeholder1-keyName", + "keyVaultEndpoint" : "placeholder1-keyVaultEndpoint.com" + }))), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + + // Needs KMS to encrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/encrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + // Check that `out` contains name. + bson_t out_bson; + ASSERT(_mongocrypt_binary_to_bson(out, &out_bson)); + char *pattern = BSON_STR({"masterKey" : {"provider" : "azure:name1"}}); + _assert_match_bson(&out_bson, TMP_BSON(pattern)); + bson_destroy(&out_bson); + mongocrypt_binary_destroy(out); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test creating two Azure keys with different named providers. + // This is intended to test that they do not share cache entries. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({ + "azure:name1" : { + "tenantId" : "placeholder1-tenantId", + "clientId" : "placeholder1-clientId", + "clientSecret" : "placeholder1-clientSecret", + "identityPlatformEndpoint" : "placeholder1-identityPlatformEndpoint.com" + }, + "azure:name2" : { + "tenantId" : "placeholder2-tenantId", + "clientId" : "placeholder2-clientId", + "clientSecret" : "placeholder2-clientSecret", + "identityPlatformEndpoint" : "placeholder2-identityPlatformEndpoint.com" + } + })); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create with `azure:name1`. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK( + mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({ + "provider" : "azure:name1", + "keyName" : "placeholder1-keyName", + "keyVaultEndpoint" : "placeholder1-keyVaultEndpoint.com" + }))), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to encrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/encrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + // Check that `out` contains name. + bson_t out_bson; + ASSERT(_mongocrypt_binary_to_bson(out, &out_bson)); + char *pattern = BSON_STR({"masterKey" : {"provider" : "azure:name1"}}); + _assert_match_bson(&out_bson, TMP_BSON(pattern)); + bson_destroy(&out_bson); + mongocrypt_binary_destroy(out); + mongocrypt_ctx_destroy(ctx); + } + + // Create with `azure:name2`. Expect a separate oauth token is needed. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK( + mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({ + "provider" : "azure:name2", + "keyName" : "placeholder2-keyName", + "keyVaultEndpoint" : "placeholder2-keyVaultEndpoint.com" + }))), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder2-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to encrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder2-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/encrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + // Check that `out` contains name. + bson_t out_bson; + ASSERT(_mongocrypt_binary_to_bson(out, &out_bson)); + char *pattern = BSON_STR({"masterKey" : {"provider" : "azure:name2"}}); + _assert_match_bson(&out_bson, TMP_BSON(pattern)); + bson_destroy(&out_bson); + mongocrypt_binary_destroy(out); + mongocrypt_ctx_destroy(ctx); + } + mongocrypt_destroy(crypt); + } + + // Test successfully creating an KMIP DEK with a named KMS provider + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"kmip:name1" : {"endpoint" : "placeholder1-endpoint.com"}})); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create with named KMS provider. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK( + mongocrypt_ctx_setopt_key_encryption_key(ctx, + TEST_BSON(BSON_STR({"provider" : "kmip:name1", "keyId" : "12"}))), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + + // Needs KMS to Get KEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-endpoint.com:5696"); + // Assert request is a Get. + { + mongocrypt_binary_t *request = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kctx, request), kctx); + ASSERT_STREQUAL(kmip_get_operation_type(request), "Get"); + mongocrypt_binary_destroy(request); + } + // Feed response to Get. + ASSERT_OK(kms_ctx_feed_all(kctx, KMIP_GET_RESPONSE, (uint32_t)(sizeof(KMIP_GET_RESPONSE))), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + // Check that `out` contains name. + bson_t out_bson; + ASSERT(_mongocrypt_binary_to_bson(out, &out_bson)); + char *pattern = BSON_STR({"masterKey" : {"provider" : "kmip:name1"}}); + _assert_match_bson(&out_bson, TMP_BSON(pattern)); + bson_destroy(&out_bson); + mongocrypt_binary_destroy(out); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test creating a KMIP key when `keyId` is not passed. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"kmip:name1" : {"endpoint" : "placeholder1-endpoint.com"}})); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create with named KMS provider. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({"provider" : "kmip:name1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + + // Needs KMS to Register KEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-endpoint.com:5696"); + // Assert request is a Register. + { + mongocrypt_binary_t *request = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kctx, request), kctx); + ASSERT_STREQUAL(kmip_get_operation_type(request), "Register"); + mongocrypt_binary_destroy(request); + } + // Feed response to Register. + ASSERT_OK(kms_ctx_feed_all(kctx, KMIP_REGISTER_RESPONSE, (uint32_t)(sizeof(KMIP_REGISTER_RESPONSE))), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to Activate KEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-endpoint.com:5696"); + // Assert request is a Activate. + { + mongocrypt_binary_t *request = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kctx, request), kctx); + ASSERT_STREQUAL(kmip_get_operation_type(request), "Activate"); + mongocrypt_binary_destroy(request); + } + // Feed response to Activate. + ASSERT_OK(kms_ctx_feed_all(kctx, KMIP_ACTIVATE_RESPONSE, (uint32_t)(sizeof(KMIP_ACTIVATE_RESPONSE))), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to Get KEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-endpoint.com:5696"); + // Assert request is a Get. + { + mongocrypt_binary_t *request = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kctx, request), kctx); + ASSERT_STREQUAL(kmip_get_operation_type(request), "Get"); + mongocrypt_binary_destroy(request); + } + // Feed response to Get. + ASSERT_OK(kms_ctx_feed_all(kctx, KMIP_GET_RESPONSE, (uint32_t)(sizeof(KMIP_GET_RESPONSE))), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *out = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, out), ctx); + // Check that `out` contains name. + bson_t out_bson; + ASSERT(_mongocrypt_binary_to_bson(out, &out_bson)); + char *pattern = BSON_STR({"masterKey" : {"provider" : "kmip:name1"}}); + _assert_match_bson(&out_bson, TMP_BSON(pattern)); + bson_destroy(&out_bson); + mongocrypt_binary_destroy(out); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } +} + +typedef struct { + mongocrypt_binary_t *kms_providers; + const char *key_alt_name; + mongocrypt_binary_t *kek; + mongocrypt_binary_t *kms_response_1; + mongocrypt_binary_t *kms_response_2; +} create_dek_args; + +// `create_dek` is a test helper to create a Data Encryption Key (DEK). +static void create_dek(_mongocrypt_tester_t *tester, create_dek_args args, _mongocrypt_buffer_t *dek) { + BSON_ASSERT_PARAM(args.kms_providers); + BSON_ASSERT_PARAM(args.key_alt_name); + BSON_ASSERT_PARAM(args.kek); + // kms_response_1 and kms_response_2 may be NULL. + + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, args.kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, args.kek), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "%s"}), args.key_alt_name)), + ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + + if (args.kms_response_1) { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + ASSERT_OK(kms_ctx_feed_all(kctx, + mongocrypt_binary_data(args.kms_response_1), + mongocrypt_binary_len(args.kms_response_1)), + kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + if (args.kms_response_2) { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + ASSERT_OK(kms_ctx_feed_all(kctx, + mongocrypt_binary_data(args.kms_response_2), + mongocrypt_binary_len(args.kms_response_2)), + kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + _mongocrypt_buffer_copy_from_binary(dek, bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +static void test_explicit_with_named_kms_provider_for_azure(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({ + "azure:name1" : { + "tenantId" : "placeholder1-tenantId", + "clientId" : "placeholder1-clientId", + "clientSecret" : "placeholder1-clientSecret", + "identityPlatformEndpoint" : "placeholder1-identityPlatformEndpoint.com" + }, + "azure:name2" : { + "tenantId" : "placeholder2-tenantId", + "clientId" : "placeholder2-clientId", + "clientSecret" : "placeholder2-clientSecret", + "identityPlatformEndpoint" : "placeholder2-identityPlatformEndpoint.com" + } + })); + + // Create `dek1` from `azure:name1` + _mongocrypt_buffer_t dek1; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "azure1", + .kek = TEST_BSON(BSON_STR({ + "provider" : "azure:name1", + "keyName" : "placeholder1-keyName", + "keyVaultEndpoint" : "placeholder1-keyVaultEndpoint.com" + })), + .kms_response_1 = TEST_FILE("./test/data/kms-azure/oauth-response.txt"), + .kms_response_2 = TEST_FILE("./test/data/kms-azure/encrypt-response.txt")}, + &dek1); + + // Create `dek2` from `azure:name2` + _mongocrypt_buffer_t dek2; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "azure2", + .kek = TEST_BSON(BSON_STR({ + "provider" : "azure:name2", + "keyName" : "placeholder2-keyName", + "keyVaultEndpoint" : "placeholder2-keyVaultEndpoint.com" + })), + .kms_response_1 = TEST_FILE("./test/data/kms-azure/oauth-response.txt"), + .kms_response_2 = TEST_FILE("./test/data/kms-azure/encrypt-response.txt")}, + &dek2); + + // Test encrypting. + _mongocrypt_buffer_t ciphertext; + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Test encrypting without cached DEK. Store result for later decryption. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "azure1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + _mongocrypt_buffer_copy_from_binary(&ciphertext, bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Test encrypting with cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "azure1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + // DEK is already cached. State transitions directly to ready. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + mongocrypt_destroy(crypt); + } + + // Test decrypting. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Test decrypting without cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Test decrypting with cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + // DEK is already cached. State transitions directly to ready. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + mongocrypt_destroy(crypt); + } + + // Test decrypting with a cached oauth token, but not a cached DEK. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Decrypt. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Recreate the `mongocrypt_ctx_t`. Expect the oauth token to be cached but the DEK not to be cached. + mongocrypt_ctx_destroy(ctx); + + ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test encrypting with two different named Azure. + // Expect two separate oauth token requests. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Encrypt with azure:name1 + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "azure1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Encrypt with azure:name2 + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "azure2"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek2)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder2-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder2-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + mongocrypt_destroy(crypt); + } + + // Test encrypting when access token is included in KMS providers. + { + mongocrypt_t *crypt = mongocrypt_new(); + + mongocrypt_binary_t *kms_providers_withAccessToken = + TEST_BSON(BSON_STR({"azure:name3_withAccessToken" : {"accessToken" : "placeholder3-accesstoken"}})); + + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers_withAccessToken), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create `dek3` from `azure:name3_withAccessToken` + _mongocrypt_buffer_t dek3; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers_withAccessToken, + .key_alt_name = "azure3", + .kek = TEST_BSON(BSON_STR({ + "provider" : "azure:name3_withAccessToken", + "keyName" : "placeholder3-keyName", + "keyVaultEndpoint" : "placeholder3-keyVaultEndpoint.com" + })), + // Does not need KMS for oauth token. + .kms_response_1 = TEST_FILE("./test/data/kms-azure/encrypt-response.txt")}, + &dek3); + + // Encrypt with `dek3`. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "azure3"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek3)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Does not need KMS for oauth token. + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder3-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + _mongocrypt_buffer_cleanup(&dek3); + mongocrypt_destroy(crypt); + } + + _mongocrypt_buffer_cleanup(&ciphertext); + _mongocrypt_buffer_cleanup(&dek2); + _mongocrypt_buffer_cleanup(&dek1); +} + +static void test_explicit_with_named_kms_provider_for_gcp(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *kms_providers = TEST_BSON( + BSON_STR({ + "gcp:name1" : + {"email" : "placeholder1-email", "privateKey" : "%s", "endpoint" : "placeholder1-oauthEndpoint.com"}, + "gcp:name2" : + {"email" : "placeholder2-email", "privateKey" : "%s", "endpoint" : "placeholder2-oauthEndpoint.com"} + }), + GCP_PRIVATEKEY1, + GCP_PRIVATEKEY2); + + // Create `dek1` from `gcp:name1` + _mongocrypt_buffer_t dek1; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "gcp1", + .kek = TEST_BSON(BSON_STR({ + "provider" : "gcp:name1", + "projectId" : "placeholder1-projectId", + "location" : "placeholder1-location", + "keyRing" : "placeholder1-keyRing", + "keyName" : "placeholder1-keyName", + "endpoint" : "placeholder1-kmsEndpoint.com" + })), + .kms_response_1 = TEST_FILE("./test/data/kms-gcp/oauth-response.txt"), + .kms_response_2 = TEST_FILE("./test/data/kms-gcp/encrypt-response.txt")}, + &dek1); + + // Create `dek2` from `gcp:name2` + _mongocrypt_buffer_t dek2; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "gcp2", + .kek = TEST_BSON(BSON_STR({ + "provider" : "gcp:name2", + "projectId" : "placeholder2-projectId", + "location" : "placeholder2-location", + "keyRing" : "placeholder2-keyRing", + "keyName" : "placeholder2-keyName", + "endpoint" : "placeholder2-kmsEndpoint.com" + })), + .kms_response_1 = TEST_FILE("./test/data/kms-gcp/oauth-response.txt"), + .kms_response_2 = TEST_FILE("./test/data/kms-gcp/encrypt-response.txt")}, + &dek2); + + // Test encrypting. + _mongocrypt_buffer_t ciphertext; + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Test encrypting without cached DEK. Store result for later decryption. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "gcp1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-oauthEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-kmsEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + _mongocrypt_buffer_copy_from_binary(&ciphertext, bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Test encrypting with cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "gcp1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + // DEK is already cached. State transitions directly to ready. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + mongocrypt_destroy(crypt); + } + + // Test decrypting. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Test decrypting without cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-oauthEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-kmsEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Test decrypting with cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + // DEK is already cached. State transitions directly to ready. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + mongocrypt_destroy(crypt); + } + + // Test decrypting with a cached oauth token, but not a cached DEK. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Decrypt. + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-oauthEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Recreate the `mongocrypt_ctx_t`. Expect the oauth token to be cached but the DEK not to be cached. + mongocrypt_ctx_destroy(ctx); + + ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-kmsEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test encrypting with two different named Gcp. + // Expect two separate oauth token requests. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Encrypt with gcp:name1 + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "gcp1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-oauthEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-kmsEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Encrypt with gcp:name2 + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "gcp2"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek2)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder2-oauthEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder2-kmsEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + mongocrypt_destroy(crypt); + } + + // Test calling `mongocrypt_ctx_kms_done` before responding to an oauth request. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "gcp1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_FAILS(mongocrypt_ctx_kms_done(ctx), ctx, "KMS response unfinished"); + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test calling `mongocrypt_ctx_kms_done` before responding to a decrypt request. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "gcp1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-oauthEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-kmsEndpoint.com:443"); + ASSERT_FAILS(mongocrypt_ctx_kms_done(ctx), ctx, "KMS response unfinished"); + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + // Test encrypting when access token is included in KMS providers. + { + mongocrypt_t *crypt = mongocrypt_new(); + mongocrypt_binary_t *kms_providers_withAccessToken = + TEST_BSON(BSON_STR({"gcp:name3_withAccessToken" : {"accessToken" : "placeholder3-accesstoken"}})); + + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers_withAccessToken), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Create `dek3` from `gcp:name3_withAccessToken` + _mongocrypt_buffer_t dek3; + { + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers_withAccessToken, + .key_alt_name = "gcp3", + .kek = TEST_BSON(BSON_STR({ + "provider" : "gcp:name3_withAccessToken", + "projectId" : "placeholder3-projectId", + "location" : "placeholder3-location", + "keyRing" : "placeholder3-keyRing", + "keyName" : "placeholder3-keyName", + "endpoint" : "placeholder3-kmsEndpoint.com" + })), + // Does not need KMS for oauth token. + + .kms_response_1 = TEST_FILE("./test/data/kms-gcp/encrypt-response.txt")}, + &dek3); + } + + // Encrypt with `dek3`. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "gcp3"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek3)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Does not need KMS for oauth token. + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder3-kmsEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-gcp/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + _mongocrypt_buffer_cleanup(&dek3); + mongocrypt_destroy(crypt); + } + + _mongocrypt_buffer_cleanup(&ciphertext); + _mongocrypt_buffer_cleanup(&dek2); + _mongocrypt_buffer_cleanup(&dek1); +} + +static void test_explicit_with_named_kms_provider_for_aws(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({ + "aws:name1" : {"accessKeyId" : "placeholder1-aki", "secretAccessKey" : "placeholder1-sak"}, + "aws:name2" : {"accessKeyId" : "placeholder2-aki", "secretAccessKey" : "placeholder2-sak"} + })); + + // Create `dek1` from `aws:name1` + _mongocrypt_buffer_t dek1; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "aws1", + .kek = TEST_BSON(BSON_STR({ + "provider" : "aws:name1", + "region" : "placeholder1-region", + "key" : "placeholder1-key", + "endpoint" : "placeholder1-endpoint.com" + })), + .kms_response_1 = TEST_FILE("./test/data/kms-aws/encrypt-response.txt")}, + &dek1); + + // Create `dek2` from `aws:name2` + _mongocrypt_buffer_t dek2; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "aws2", + .kek = TEST_BSON(BSON_STR({ + "provider" : "aws:name2", + "region" : "placeholder2-region", + "key" : "placeholder2-key", + "endpoint" : "placeholder2-endpoint.com" + })), + .kms_response_1 = TEST_FILE("./test/data/kms-aws/encrypt-response.txt")}, + &dek2); + + // Test encrypting. + _mongocrypt_buffer_t ciphertext; + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Test encrypting without cached DEK. Store result for later decryption. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "aws1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-endpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-aws/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + _mongocrypt_buffer_copy_from_binary(&ciphertext, bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Test encrypting with cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "aws1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + // DEK is already cached. State transitions directly to ready. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + mongocrypt_destroy(crypt); + } + + // Test decrypting. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Test decrypting without cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS to decrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-endpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/example/kms-decrypt-reply.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Test decrypting with cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + // DEK is already cached. State transitions directly to ready. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + mongocrypt_destroy(crypt); + } + + _mongocrypt_buffer_cleanup(&ciphertext); + _mongocrypt_buffer_cleanup(&dek2); + _mongocrypt_buffer_cleanup(&dek1); +} + +static void test_explicit_with_named_kms_provider_for_kmip(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({ + "kmip:name1" : {"endpoint" : "placeholder1-endpoint.com"}, + "kmip:name2" : {"endpoint" : "placeholder2-endpoint.com"} + })); + + mongocrypt_binary_t *get_response = + mongocrypt_binary_new_from_data((uint8_t *)KMIP_GET_RESPONSE, (uint32_t)sizeof(KMIP_GET_RESPONSE)); + + // Create `dek1` from `kmip:name1` + _mongocrypt_buffer_t dek1; + + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "kmip1", + .kek = TEST_BSON(BSON_STR({"provider" : "kmip:name1", "keyId" : "12"})), + .kms_response_1 = get_response}, + &dek1); + + // Create `dek2` from `kmip:name2` + _mongocrypt_buffer_t dek2; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "kmip2", + .kek = TEST_BSON(BSON_STR({"provider" : "kmip:name2", "keyId" : "12"})), + .kms_response_1 = get_response}, + &dek2); + + // Test encrypting. + _mongocrypt_buffer_t ciphertext; + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Test encrypting without cached DEK. Store result for later decryption. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "kmip1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS to Get KEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-endpoint.com:5696"); + // Assert request is a Get. + { + mongocrypt_binary_t *request = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kctx, request), kctx); + ASSERT_STREQUAL(kmip_get_operation_type(request), "Get"); + mongocrypt_binary_destroy(request); + } + // Feed response to Get. + ASSERT_OK(kms_ctx_feed_all(kctx, KMIP_GET_RESPONSE, (uint32_t)(sizeof(KMIP_GET_RESPONSE))), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + _mongocrypt_buffer_copy_from_binary(&ciphertext, bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Test encrypting with cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "kmip1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_DETERMINISTIC_STR, -1), ctx); + ASSERT_OK(mongocrypt_ctx_explicit_encrypt_init(ctx, TEST_BSON(BSON_STR({"v" : "foo"}))), ctx); + // DEK is already cached. State transitions directly to ready. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + mongocrypt_destroy(crypt); + } + + // Test decrypting. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + // Test decrypting without cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS to Get KEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-endpoint.com:5696"); + // Assert request is a Get. + { + mongocrypt_binary_t *request = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_kms_ctx_message(kctx, request), kctx); + ASSERT_STREQUAL(kmip_get_operation_type(request), "Get"); + mongocrypt_binary_destroy(request); + } + // Feed response to Get. + ASSERT_OK(kms_ctx_feed_all(kctx, KMIP_GET_RESPONSE, (uint32_t)(sizeof(KMIP_GET_RESPONSE))), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + + // Test decrypting with cached DEK. + { + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_explicit_decrypt_init(ctx, _mongocrypt_buffer_as_binary(&ciphertext)), ctx); + // DEK is already cached. State transitions directly to ready. + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + ASSERT_MONGOCRYPT_BINARY_EQUAL_BSON(TEST_BSON(BSON_STR({"v" : "foo"})), bin); + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + } + mongocrypt_destroy(crypt); + } + + _mongocrypt_buffer_cleanup(&ciphertext); + _mongocrypt_buffer_cleanup(&dek2); + _mongocrypt_buffer_cleanup(&dek1); + mongocrypt_binary_destroy(get_response); +} + +static void test_rewrap_with_named_kms_provider_local2local(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"local:name1" : {"key" : "%s"}, "local:name2" : {"key" : "%s"}}), + LOCAL_KEK1_BASE64, + LOCAL_KEK2_BASE64); + + // Create `dek1` from `local:name1` + _mongocrypt_buffer_t dek1; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "local1", + .kek = TEST_BSON(BSON_STR({"provider" : "local:name1"}))}, + &dek1); + + // Rewrap `dek1` with `local:name2`. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({"provider" : "local:name2"}))), + ctx); + mongocrypt_binary_t *filter = TEST_BSON(BSON_STR({})); + ASSERT_OK(mongocrypt_ctx_rewrap_many_datakey_init(ctx, filter), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + // Check resulting document contains expected name. + { + bson_t bin_bson; + ASSERT(_mongocrypt_binary_to_bson(bin, &bin_bson)); + char *pattern = BSON_STR({"v" : [ {"masterKey" : {"provider" : "local:name2"}} ]}); + _assert_match_bson(&bin_bson, TMP_BSON(pattern)); + } + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + _mongocrypt_buffer_cleanup(&dek1); +} + +static void test_rewrap_with_named_kms_provider_azure2azure(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *kms_providers = TEST_BSON(BSON_STR({ + "azure:name1" : { + "tenantId" : "placeholder1-tenantId", + "clientId" : "placeholder1-clientId", + "clientSecret" : "placeholder1-clientSecret", + "identityPlatformEndpoint" : "placeholder1-identityPlatformEndpoint.com" + }, + "azure:name2" : { + "tenantId" : "placeholder2-tenantId", + "clientId" : "placeholder2-clientId", + "clientSecret" : "placeholder2-clientSecret", + "identityPlatformEndpoint" : "placeholder2-identityPlatformEndpoint.com" + } + })); + + // Create `dek1` from `azure:name1` + _mongocrypt_buffer_t dek1; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "azure1", + .kek = TEST_BSON(BSON_STR({ + "provider" : "azure:name1", + "keyName" : "placeholder1-keyName", + "keyVaultEndpoint" : "placeholder1-keyVaultEndpoint.com" + })), + .kms_response_1 = TEST_FILE("./test/data/kms-azure/oauth-response.txt"), + .kms_response_2 = TEST_FILE("./test/data/kms-azure/encrypt-response.txt")}, + &dek1); + + // Rewrap `dek1` with `azure:name2`. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({ + "provider" : "azure:name2", + "keyName" : "placeholder2-keyName", + "keyVaultEndpoint" : "placeholder2-keyVaultEndpoint.com" + }))), + ctx); + mongocrypt_binary_t *filter = TEST_BSON(BSON_STR({})); + ASSERT_OK(mongocrypt_ctx_rewrap_many_datakey_init(ctx, filter), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token from azure:name1. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK from azure:name1. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS for oauth token from azure:name2. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder2-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to encrypt DEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder2-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/encrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + // Check resulting document contains expected name. + { + bson_t bin_bson; + ASSERT(_mongocrypt_binary_to_bson(bin, &bin_bson)); + char *pattern = BSON_STR({"v" : [ {"masterKey" : {"provider" : "azure:name2"}} ]}); + _assert_match_bson(&bin_bson, TMP_BSON(pattern)); + } + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + _mongocrypt_buffer_cleanup(&dek1); +} + +static void test_rewrap_with_named_kms_provider_azure2local(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({ + "azure:name1" : { + "tenantId" : "placeholder1-tenantId", + "clientId" : "placeholder1-clientId", + "clientSecret" : "placeholder1-clientSecret", + "identityPlatformEndpoint" : "placeholder1-identityPlatformEndpoint.com" + }, + "local:name1" : {"key" : "%s"} + }), + LOCAL_KEK1_BASE64); + + // Create `dek1` from `azure:name1` + _mongocrypt_buffer_t dek1; + create_dek(tester, + (create_dek_args){.kms_providers = kms_providers, + .key_alt_name = "azure1", + .kek = TEST_BSON(BSON_STR({ + "provider" : "azure:name1", + "keyName" : "placeholder1-keyName", + "keyVaultEndpoint" : "placeholder1-keyVaultEndpoint.com" + })), + .kms_response_1 = TEST_FILE("./test/data/kms-azure/oauth-response.txt"), + .kms_response_2 = TEST_FILE("./test/data/kms-azure/encrypt-response.txt")}, + &dek1); + + // Rewrap `dek1` with `local:name1`. + { + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK(mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({"provider" : "local:name1"}))), + ctx); + mongocrypt_binary_t *filter = TEST_BSON(BSON_STR({})); + ASSERT_OK(mongocrypt_ctx_rewrap_many_datakey_init(ctx, filter), ctx); + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_MONGO_KEYS); + ASSERT_OK(mongocrypt_ctx_mongo_feed(ctx, _mongocrypt_buffer_as_binary(&dek1)), ctx); + ASSERT_OK(mongocrypt_ctx_mongo_done(ctx), ctx); + + // Needs KMS for oauth token from azure:name1. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-identityPlatformEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/oauth-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + // Needs KMS to decrypt DEK from azure:name1. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + const char *endpoint; + ASSERT_OK(mongocrypt_kms_ctx_endpoint(kctx, &endpoint), kctx); + ASSERT_STREQUAL(endpoint, "placeholder1-keyVaultEndpoint.com:443"); + ASSERT_OK(mongocrypt_kms_ctx_feed(kctx, TEST_FILE("./test/data/kms-azure/decrypt-response.txt")), kctx); + kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(!kctx); + ASSERT_OK(mongocrypt_ctx_kms_done(ctx), ctx); + } + + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_READY); + mongocrypt_binary_t *bin = mongocrypt_binary_new(); + ASSERT_OK(mongocrypt_ctx_finalize(ctx, bin), ctx); + // Check resulting document contains expected name. + { + bson_t bin_bson; + ASSERT(_mongocrypt_binary_to_bson(bin, &bin_bson)); + char *pattern = BSON_STR({"v" : [ {"masterKey" : {"provider" : "local:name1"}} ]}); + _assert_match_bson(&bin_bson, TMP_BSON(pattern)); + } + mongocrypt_binary_destroy(bin); + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); + } + + _mongocrypt_buffer_cleanup(&dek1); +} + +static void test_mongocrypt_kms_ctx_get_kms_provider(_mongocrypt_tester_t *tester) { + mongocrypt_binary_t *kms_providers = + TEST_BSON(BSON_STR({"kmip:name1" : {"endpoint" : "placeholder1-endpoint.com"}})); + + mongocrypt_t *crypt = mongocrypt_new(); + ASSERT_OK(mongocrypt_setopt_kms_providers(crypt, kms_providers), crypt); + ASSERT_OK(_mongocrypt_init_for_test(crypt), crypt); + + mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt); + ASSERT_OK( + mongocrypt_ctx_setopt_key_encryption_key(ctx, TEST_BSON(BSON_STR({"provider" : "kmip:name1", "keyId" : "12"}))), + ctx); + ASSERT_OK(mongocrypt_ctx_setopt_key_alt_name(ctx, TEST_BSON(BSON_STR({"keyAltName" : "kmip1"}))), ctx); + ASSERT_OK(mongocrypt_ctx_datakey_init(ctx), ctx); + + // Needs KMS to Get KEK. + { + ASSERT_STATE_EQUAL(mongocrypt_ctx_state(ctx), MONGOCRYPT_CTX_NEED_KMS); + mongocrypt_kms_ctx_t *kctx = mongocrypt_ctx_next_kms_ctx(ctx); + ASSERT(kctx); + ASSERT_STREQUAL(mongocrypt_kms_ctx_get_kms_provider(kctx, NULL /* len */), "kmip:name1"); + } + + mongocrypt_ctx_destroy(ctx); + mongocrypt_destroy(crypt); +} + +void _mongocrypt_tester_install_named_kms_providers(_mongocrypt_tester_t *tester) { + INSTALL_TEST(test_configuring_named_kms_providers); + INSTALL_TEST(test_create_datakey_with_named_kms_provider); + INSTALL_TEST(test_explicit_with_named_kms_provider_for_azure); + INSTALL_TEST(test_explicit_with_named_kms_provider_for_gcp); + INSTALL_TEST(test_explicit_with_named_kms_provider_for_aws); + INSTALL_TEST(test_explicit_with_named_kms_provider_for_kmip); + INSTALL_TEST(test_rewrap_with_named_kms_provider_local2local); + INSTALL_TEST(test_rewrap_with_named_kms_provider_azure2azure); + INSTALL_TEST(test_rewrap_with_named_kms_provider_azure2local); + INSTALL_TEST(test_mongocrypt_kms_ctx_get_kms_provider); +} diff --git a/ext/libmongocrypt/libmongocrypt/test/util/HELP.autogen b/ext/libmongocrypt/libmongocrypt/test/util/HELP.autogen index b20d5f1..1c1ade9 100644 --- a/ext/libmongocrypt/libmongocrypt/test/util/HELP.autogen +++ b/ext/libmongocrypt/libmongocrypt/test/util/HELP.autogen @@ -30,6 +30,7 @@ "csfle create_datakey\n" " --kms_provider \n" " --key_alt_names \n" +" --key_material \n" "\n" " AWS options.\n" " --aws_kek_region \n" @@ -52,6 +53,7 @@ " KMIP options.\n" " --kmip_kek_endpoint \n" " --kmip_kek_keyid \n" +" --kmip_kek_delegated \n" "\n" "csfle auto_encrypt\n" " --command or --command_file \n" @@ -99,4 +101,4 @@ "csfle auto_decrypt --document '{ 'insert' : 'coll', 'documents' : [ { 'ssn' : { '$binary' : { 'base64': 'ARG+PK8ud0RZlDIzKwQmFoMCOuSIPyrfYleSqMZRXgaPCQOAurv0LTLNL6Tn/G7TuVOyf/Qv3j6VxSxCQEeu/yO7vv/UDE5niDE0itjOqjmf5Q==', 'subType' : '06' } } } ] }'\n" "\n" "csfle explicit_encrypt --key_id 'Eb48ry53RFmUMjMrBCYWgw==' --value '{'v': 'test'}' --algorithm 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'\n" -"``\n" \ No newline at end of file +"```\n" \ No newline at end of file diff --git a/ext/libmongocrypt/libmongocrypt/test/util/README.md b/ext/libmongocrypt/libmongocrypt/test/util/README.md index 475b212..575485f 100644 --- a/ext/libmongocrypt/libmongocrypt/test/util/README.md +++ b/ext/libmongocrypt/libmongocrypt/test/util/README.md @@ -53,6 +53,7 @@ csfle create_datakey KMIP options. --kmip_kek_endpoint --kmip_kek_keyid + --kmip_kek_delegated csfle auto_encrypt --command or --command_file diff --git a/ext/libmongocrypt/libmongocrypt/test/util/csfle.c b/ext/libmongocrypt/libmongocrypt/test/util/csfle.c index a98bfa9..bf12c89 100644 --- a/ext/libmongocrypt/libmongocrypt/test/util/csfle.c +++ b/ext/libmongocrypt/libmongocrypt/test/util/csfle.c @@ -238,6 +238,10 @@ static void fn_createdatakey(bson_t *args) { BSON_APPEND_UTF8(&kmip_kek, "keyId", bson_req_utf8(args, "kmip_kek_keyid")); } + if (bson_has_field(args, "kmip_kek_delegated")) { + BSON_APPEND_BOOL(&kmip_kek, "delegated", bson_get_bool(args, "kmip_kek_delegated", true)); + } + bin = util_bson_to_bin(&kmip_kek); if (!mongocrypt_ctx_setopt_key_encryption_key(ctx, bin)) { ERREXIT_CTX(ctx); diff --git a/ext/libmongocrypt/libmongocrypt/test/util/make_includes.py b/ext/libmongocrypt/libmongocrypt/test/util/make_includes.py index d6fd533..199e9ce 100644 --- a/ext/libmongocrypt/libmongocrypt/test/util/make_includes.py +++ b/ext/libmongocrypt/libmongocrypt/test/util/make_includes.py @@ -817,7 +817,7 @@ def generate(code: str, parser: Callable[[Tokenizer], Iterable[T]], """ scan = Scanner(code) toks = LazyList(tokenize(scan)) - print('// This code is GENERATED! Do not edit!') + print('// This code is GENERATED! Do not edit! Regenerate with `test/util/make_includes.py`') print('// clang-format off') items = parser(toks) each_rendered = map(render, items) diff --git a/ext/libmongocrypt/libmongocrypt/test/util/util.c b/ext/libmongocrypt/libmongocrypt/test/util/util.c index 5d1b082..ac18ce0 100644 --- a/ext/libmongocrypt/libmongocrypt/test/util/util.c +++ b/ext/libmongocrypt/libmongocrypt/test/util/util.c @@ -531,9 +531,22 @@ static bool _state_need_kms(_state_machine_t *state_machine, bson_error_t *error iov.iov_base = (char *)mongocrypt_binary_data(http_req); iov.iov_len = mongocrypt_binary_len(http_req); - if (state_machine->trace) { - MONGOC_DEBUG("--> sending KMS message: \n%.*s", (int)iov.iov_len, (char *)iov.iov_base); + MONGOC_DEBUG("--> sending KMS message:"); + const char *kms_provider = mongocrypt_kms_ctx_get_kms_provider(kms_ctx, NULL); + if (0 == strcmp(kms_provider, "kmip")) { + // Print KMIP protocol as hex. + uint8_t *as_u8_ptr = iov.iov_base; + for (size_t i = 0; i < iov.iov_len; i++) { + printf("%02x", as_u8_ptr[i]); + } + } else { + // Print HTTP protocol as text. + char *as_char_ptr = iov.iov_base; + BSON_ASSERT(iov.iov_len <= INT_MAX); + printf("%.*s", (int)iov.iov_len, as_char_ptr); + } + printf("\n"); } if (!_mongoc_stream_writev_full(tls_stream, &iov, 1, sockettimeout, error)) { @@ -541,6 +554,9 @@ static bool _state_need_kms(_state_machine_t *state_machine, bson_error_t *error } /* Read and feed reply. */ + if (state_machine->trace) { + MONGOC_DEBUG("<-- read KMS reply:"); + } while (mongocrypt_kms_ctx_bytes_needed(kms_ctx) > 0) { #define BUFFER_SIZE 1024 uint8_t buf[BUFFER_SIZE]; @@ -571,7 +587,19 @@ static bool _state_need_kms(_state_machine_t *state_machine, bson_error_t *error } if (state_machine->trace) { - MONGOC_DEBUG("<-- read KMS reply: %.*s", (int)read_ret, (char *)buf); + const char *kms_provider = mongocrypt_kms_ctx_get_kms_provider(kms_ctx, NULL); + if (0 == strcmp(kms_provider, "kmip")) { + // Print KMIP protocol as hex. + for (ssize_t i = 0; i < read_ret; i++) { + printf("%02x", buf[i]); + } + } else { + char *as_char_ptr = (char *)buf; + // Print HTTP protocol as text. + BSON_ASSERT(read_ret >= 0); + BSON_ASSERT(read_ret <= INT_MAX); + printf("%.*s", (int)read_ret, as_char_ptr); + } } mongocrypt_binary_destroy(http_reply); @@ -581,6 +609,9 @@ static bool _state_need_kms(_state_machine_t *state_machine, bson_error_t *error goto fail; } } + if (state_machine->trace) { + printf("\n"); + } kms_ctx = mongocrypt_ctx_next_kms_ctx(state_machine->ctx); } /* When NULL is returned by mongocrypt_ctx_next_kms_ctx, this can either be @@ -631,6 +662,7 @@ static bool _state_ready(_state_machine_t *state_machine, bson_t *result, bson_e const char *_state_string(mongocrypt_ctx_state_t state) { switch (state) { case MONGOCRYPT_CTX_ERROR: return "MONGOCRYPT_CTX_ERROR"; + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: return "MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB"; case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: return "MONGOCRYPT_CTX_NEED_MONGO_COLLINFO"; case MONGOCRYPT_CTX_NEED_MONGO_MARKINGS: return "MONGOCRYPT_CTX_NEED_MONGO_MARKINGS"; case MONGOCRYPT_CTX_NEED_MONGO_KEYS: return "MONGOCRYPT_CTX_NEED_MONGO_KEYS"; @@ -666,6 +698,9 @@ bool _csfle_state_machine_run(_state_machine_t *state_machine, bson_t *result, b switch (mongocrypt_ctx_state(state_machine->ctx)) { default: case MONGOCRYPT_CTX_ERROR: _test_ctx_check_error(state_machine->ctx, error, true); goto fail; + case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO_WITH_DB: + ERREXIT("Obtaining collection infos on separate databases is not yet supported"); + break; case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: if (!_state_need_mongo_collinfo(state_machine, error)) { goto fail; diff --git a/lib/libmongocrypt_helper/version.rb b/lib/libmongocrypt_helper/version.rb index 5ce1eed..5b6aada 100644 --- a/lib/libmongocrypt_helper/version.rb +++ b/lib/libmongocrypt_helper/version.rb @@ -1,5 +1,5 @@ module LibmongocryptHelper - VERSION = '1.8.0.0.1001' + VERSION = '1.11.0.0.1001' - LIBMONGOCRYPT_VERSION = '1.8.0' + LIBMONGOCRYPT_VERSION = '1.11.0' end diff --git a/sbom.json b/sbom.json index 4959f83..21c7c9f 100644 --- a/sbom.json +++ b/sbom.json @@ -1,31 +1,31 @@ { "components": [ { - "bom-ref": "pkg:github/mongodb/libmongocrypt@1.8.0", + "bom-ref": "pkg:github/mongodb/libmongocrypt@1.11.0", "externalReferences": [ { "type": "distribution", - "url": "https://github.com/mongodb/libmongocrypt/archive/refs/tags/1.8.0.tar.gz" + "url": "https://github.com/mongodb/libmongocrypt/archive/refs/tags/1.11.0.tar.gz" }, { "type": "website", - "url": "https://github.com/mongodb/libmongocrypt/tree/1.8.0" + "url": "https://github.com/mongodb/libmongocrypt/tree/1.11.0" } ], "group": "mongodb", "name": "libmongocrypt", - "purl": "pkg:github/mongodb/libmongocrypt@1.8.0", + "purl": "pkg:github/mongodb/libmongocrypt@1.11.0", "type": "library", - "version": "1.8.0" + "version": "1.11.0" } ], "dependencies": [ { - "ref": "pkg:github/mongodb/libmongocrypt@1.8.0" + "ref": "pkg:github/mongodb/libmongocrypt@1.11.0" } ], "metadata": { - "timestamp": "2024-06-12T07:24:32.253682+00:00", + "timestamp": "2024-08-20T08:21:41.909456+00:00", "tools": [ { "externalReferences": [ @@ -69,8 +69,9 @@ ] }, "serialNumber": "urn:uuid:67ce9be7-c1c0-436f-a7d7-c636db7b882b", - "version": 1, + "version": 2, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", - "specVersion": "1.5" + "specVersion": "1.5", + "vulnerabilities": [] }