diff --git a/.bazelrc b/.bazelrc index 7b1f772..ace2519 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,10 +1,3 @@ -build:asan --strip=never -build:asan --copt -fsanitize=address -build:asan --copt -DADDRESS_SANITIZER -build:asan --copt -g -build:asan --copt -fno-omit-frame-pointer -build:asan --linkopt -fsanitize=address - # For all builds, use C++17 build --cxxopt="-std=c++17" @@ -12,3 +5,53 @@ build --cxxopt="-std=c++17" build:apple_silicon --cpu=darwin_arm64 build:apple_silicon --features=oso_prefix_is_pwd +# ----------------------------------------------------------------------------- +# Sanitizer / dynamic-analysis configurations. +# +# Pick one with `--config=`, e.g. +# bazel test --config=asan //toolbelt:sockets_test +# bazel test --config=tsan //toolbelt:sockets_test +# bazel test --config=valgrind //toolbelt:sockets_test +# +# All three configs preserve debug information so failures point back to +# meaningful source locations. +# ----------------------------------------------------------------------------- + +# AddressSanitizer. Detects use-after-free, heap/stack/global buffer +# overflows, use-after-return, etc. +build:asan --strip=never +build:asan --copt=-fsanitize=address +build:asan --copt=-DADDRESS_SANITIZER +build:asan --copt=-g +build:asan --copt=-O1 +build:asan --copt=-fno-omit-frame-pointer +build:asan --linkopt=-fsanitize=address +# Note: leak detection (LSan) is only supported on Linux; opting out keeps the +# config portable to macOS. On Linux you can enable it with +# --test_env=ASAN_OPTIONS=halt_on_error=1:detect_leaks=1 +test:asan --test_env=ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:detect_leaks=0:print_summary=1 + +# ThreadSanitizer. Detects data races and several kinds of synchronization +# bugs. +build:tsan --strip=never +build:tsan --copt=-fsanitize=thread +build:tsan --copt=-DTHREAD_SANITIZER +build:tsan --copt=-g +build:tsan --copt=-O1 +build:tsan --copt=-fno-omit-frame-pointer +build:tsan --linkopt=-fsanitize=thread +test:tsan --test_env=TSAN_OPTIONS=halt_on_error=1:second_deadlock_stack=1:history_size=7 + +# Valgrind. Runs the unmodified binary under Memcheck. +# +# Notes: +# * Valgrind is not available on macOS arm64. Use Linux (or x86_64) to +# exercise this config. +# * --error-exitcode=1 makes the test fail on any reported error. +# * --child-silent-after-fork=yes suppresses noise from forking helpers. +build:valgrind --strip=never +build:valgrind --copt=-g +build:valgrind --copt=-O1 +build:valgrind --copt=-fno-omit-frame-pointer +test:valgrind --run_under='valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=definite,possible --track-origins=yes --child-silent-after-fork=yes --trace-children=yes' +test:valgrind --test_timeout=300 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e530d1c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,127 @@ +name: CI + +on: [push, pull_request] + +jobs: + # Plain build + test on each supported host. Mirrors the workflow used by + # the dallison/co repository so behavior stays consistent across + # projects. + test: + name: Build & test (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + - os: ubuntu-24.04-arm + - os: macos-latest + bazel_flags: --config=apple_silicon + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Install Bazel + uses: bazel-contrib/setup-bazel@0.18.0 + with: + # Avoid downloading Bazel every time. + bazelisk-cache: true + # Store the build cache per workflow. + disk-cache: ${{ github.workflow }}-${{ matrix.os }} + # Share the repository cache between workflows. + repository-cache: true + + - name: Build all targets + run: | + bazel build //... \ + --verbose_failures \ + ${{ matrix.bazel_flags }} + + - name: Run tests + run: | + bazel test //... \ + --verbose_failures \ + --test_output=errors \ + ${{ matrix.bazel_flags }} + + - name: Upload Bazel test logs + uses: actions/upload-artifact@v7 + if: failure() + with: + name: bazel-test-logs-${{ matrix.os }} + path: bazel-testlogs + + # Run the test suite under AddressSanitizer and ThreadSanitizer. Linux + # only because LSan + ASan, and TSan, behave most uniformly there. + sanitizers: + name: ${{ matrix.config }} + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + config: [asan, tsan] + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Install Bazel + uses: bazel-contrib/setup-bazel@0.18.0 + with: + bazelisk-cache: true + disk-cache: ${{ github.workflow }}-${{ matrix.config }} + repository-cache: true + + - name: Run tests under ${{ matrix.config }} + run: | + bazel test //... \ + --config=${{ matrix.config }} \ + --verbose_failures \ + --test_output=errors + + - name: Upload Bazel test logs + uses: actions/upload-artifact@v7 + if: failure() + with: + name: bazel-test-logs-${{ matrix.config }} + path: bazel-testlogs + + # Run the test suite under Valgrind's Memcheck. Valgrind is only + # available on Linux/x86_64 in practice. + valgrind: + name: valgrind + runs-on: ubuntu-latest + timeout-minutes: 45 + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Install Valgrind + run: | + sudo apt-get update + sudo apt-get install -y valgrind + + - name: Install Bazel + uses: bazel-contrib/setup-bazel@0.18.0 + with: + bazelisk-cache: true + disk-cache: ${{ github.workflow }}-valgrind + repository-cache: true + + - name: Run tests under Valgrind + run: | + bazel test //... \ + --config=valgrind \ + --verbose_failures \ + --test_output=errors + + - name: Upload Bazel test logs + uses: actions/upload-artifact@v7 + if: failure() + with: + name: bazel-test-logs-valgrind + path: bazel-testlogs diff --git a/MODULE.bazel b/MODULE.bazel index dece293..806e12f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,13 +1,13 @@ module( name = "cpp_toolbelt", - version = "2.0.2", + version = "2.1.1", ) bazel_dep(name = "platforms", version = "1.0.0") bazel_dep(name = "bazel_skylib", version = "1.9.0") bazel_dep(name = "abseil-cpp", version = "20250814.1") bazel_dep(name = "googletest", version = "1.17.0.bcr.2") -bazel_dep(name = "coroutines", version = "3.2.1") +bazel_dep(name = "coroutines", version = "3.3.1") bazel_dep(name = "rules_cc", version = "0.2.17") # For local debugging of co coroutine library. diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 3dae2d3..574c750 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -1,15 +1,191 @@ { - "lockFileVersion": 26, - "registryFileHashes": {}, + "lockFileVersion": 24, + "registryFileHashes": { + "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", + "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", + "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1", + "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215", + "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2", + "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c", + "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", + "https://bcr.bazel.build/modules/apple_support/1.22.1/MODULE.bazel": "90bd1a660590f3ceffbdf524e37483094b29352d85317060b2327fff8f3f4458", + "https://bcr.bazel.build/modules/apple_support/1.23.1/MODULE.bazel": "53763fed456a968cf919b3240427cf3a9d5481ec5466abc9d5dc51bc70087442", + "https://bcr.bazel.build/modules/apple_support/1.23.1/source.json": "d888b44312eb0ad2c21a91d026753f330caa48a25c9b2102fae75eb2b0dcfdd2", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", + "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", + "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", + "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", + "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", + "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65", + "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", + "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", + "https://bcr.bazel.build/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", + "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", + "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", + "https://bcr.bazel.build/modules/bazel_skylib/1.9.0/MODULE.bazel": "72997b29dfd95c3fa0d0c48322d05590418edef451f8db8db5509c57875fb4b7", + "https://bcr.bazel.build/modules/bazel_skylib/1.9.0/source.json": "7ad77c1e8c1b84222d9b3f3cae016a76639435744c19330b0b37c0a3c9da7dc0", + "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", + "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "https://bcr.bazel.build/modules/coroutines/3.3.1/MODULE.bazel": "96746c200b0890b9a124713598fc0eb028cb7bf04a796e393573179ce5a4d34f", + "https://bcr.bazel.build/modules/coroutines/3.3.1/source.json": "c79ca39719820a3cef8fea46a5c204f0ca1ee725acd4f2799266441faf53484d", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", + "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", + "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", + "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", + "https://bcr.bazel.build/modules/googletest/1.17.0.bcr.2/MODULE.bazel": "827f54f492a3ce549c940106d73de332c2b30cebd0c20c0bc5d786aba7f116cb", + "https://bcr.bazel.build/modules/googletest/1.17.0.bcr.2/source.json": "3664514073a819992320ffbce5825e4238459df344d8b01748af2208f8d2e1eb", + "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", + "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", + "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", + "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", + "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", + "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", + "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", + "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", + "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", + "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/23.1/MODULE.bazel": "88b393b3eb4101d18129e5db51847cd40a5517a53e81216144a8c32dfeeca52a", + "https://bcr.bazel.build/modules/protobuf/24.4/MODULE.bazel": "7bc7ce5f2abf36b3b7b7c8218d3acdebb9426aeb35c2257c96445756f970eb12", + "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", + "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", + "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", + "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", + "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", + "https://bcr.bazel.build/modules/pybind11_bazel/2.13.6/MODULE.bazel": "2d746fda559464b253b2b2e6073cb51643a2ac79009ca02100ebbc44b4548656", + "https://bcr.bazel.build/modules/pybind11_bazel/2.13.6/source.json": "6aa0703de8efb20cc897bbdbeb928582ee7beaf278bcd001ac253e1605bddfae", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", + "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", + "https://bcr.bazel.build/modules/re2/2025-08-12.bcr.1/MODULE.bazel": "e09b434b122bfb786a69179f9b325e35cb1856c3f56a7a81dd61609260ed46e1", + "https://bcr.bazel.build/modules/re2/2025-08-12.bcr.1/source.json": "a8ae7c09533bf67f9f6e5122d884d5741600b09d78dca6fc0f2f8d2ee0c2d957", + "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", + "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", + "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", + "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", + "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac", + "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", + "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", + "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", + "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", + "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", + "https://bcr.bazel.build/modules/rules_cc/0.1.4/MODULE.bazel": "bb03a452a7527ac25a7518fb86a946ef63df860b9657d8323a0c50f8504fb0b9", + "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", + "https://bcr.bazel.build/modules/rules_cc/0.2.16/MODULE.bazel": "9242fa89f950c6ef7702801ab53922e99c69b02310c39fb6e62b2bd30df2a1d4", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", + "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", + "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", + "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", + "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", + "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6", + "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.1.0/MODULE.bazel": "30d9135a2b6561c761bd67bd4990da591e6bdc128790ce3e7afd6a3558b2fb64", + "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", + "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", + "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", + "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", + "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", + "https://bcr.bazel.build/modules/rules_java/8.14.0/MODULE.bazel": "717717ed40cc69994596a45aec6ea78135ea434b8402fb91b009b9151dd65615", + "https://bcr.bazel.build/modules/rules_java/8.14.0/source.json": "8a88c4ca9e8759da53cddc88123880565c520503321e2566b4e33d0287a3d4bc", + "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", + "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", + "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", + "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", + "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", + "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", + "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", + "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", + "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", + "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", + "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", + "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", + "https://bcr.bazel.build/modules/rules_python/0.34.0/MODULE.bazel": "1d623d026e075b78c9fde483a889cda7996f5da4f36dffb24c246ab30f06513a", + "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", + "https://bcr.bazel.build/modules/rules_python/1.5.1/MODULE.bazel": "acfe65880942d44a69129d4c5c3122d57baaf3edf58ae5a6bd4edea114906bf5", + "https://bcr.bazel.build/modules/rules_python/1.5.1/source.json": "aa903e1bcbdfa1580f2b8e2d55100b7c18bc92d779ebb507fec896c75635f7bd", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95", + "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", + "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", + "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", + "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", + "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/upb/0.0.0-20230516-61a97ef/MODULE.bazel": "c0df5e35ad55e264160417fd0875932ee3c9dda63d9fccace35ac62f45e1b6f9", + "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" + }, "selectedYankedVersions": {}, "moduleExtensions": { "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { - "bzlTransitiveDigest": "Ga4z8lQy1YQ5rAMy+dOl0dqcCEBnYNCXku8x3YQmDZI=", + "bzlTransitiveDigest": "rL/34P1aFDq2GqVC2zCFgQ8nTuOC6ziogocpvG50Qz8=", "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", - "recordedInputs": [ - "REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools" - ], + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, "generatedRepoSpecs": { "com_github_jetbrains_kotlin_git": { "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository", @@ -57,185 +233,23 @@ ] } } - } - } - }, - "@@rules_python+//python/extensions:config.bzl%config": { - "general": { - "bzlTransitiveDigest": "iibnRYgg8LpcfmH7EAnVwYePC3jsVaJ6Id8XxUjSZps=", - "usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=", - "recordedInputs": [ - "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", - "REPO_MAPPING:rules_python+,pypi__build rules_python++config+pypi__build", - "REPO_MAPPING:rules_python+,pypi__click rules_python++config+pypi__click", - "REPO_MAPPING:rules_python+,pypi__colorama rules_python++config+pypi__colorama", - "REPO_MAPPING:rules_python+,pypi__importlib_metadata rules_python++config+pypi__importlib_metadata", - "REPO_MAPPING:rules_python+,pypi__installer rules_python++config+pypi__installer", - "REPO_MAPPING:rules_python+,pypi__more_itertools rules_python++config+pypi__more_itertools", - "REPO_MAPPING:rules_python+,pypi__packaging rules_python++config+pypi__packaging", - "REPO_MAPPING:rules_python+,pypi__pep517 rules_python++config+pypi__pep517", - "REPO_MAPPING:rules_python+,pypi__pip rules_python++config+pypi__pip", - "REPO_MAPPING:rules_python+,pypi__pip_tools rules_python++config+pypi__pip_tools", - "REPO_MAPPING:rules_python+,pypi__pyproject_hooks rules_python++config+pypi__pyproject_hooks", - "REPO_MAPPING:rules_python+,pypi__setuptools rules_python++config+pypi__setuptools", - "REPO_MAPPING:rules_python+,pypi__tomli rules_python++config+pypi__tomli", - "REPO_MAPPING:rules_python+,pypi__wheel rules_python++config+pypi__wheel", - "REPO_MAPPING:rules_python+,pypi__zipp rules_python++config+pypi__zipp" - ], - "generatedRepoSpecs": { - "rules_python_internal": { - "repoRuleId": "@@rules_python+//python/private:internal_config_repo.bzl%internal_config_repo", - "attributes": { - "transition_setting_generators": {}, - "transition_settings": [] - } - }, - "pypi__build": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/e2/03/f3c8ba0a6b6e30d7d18c40faab90807c9bb5e9a1e3b2fe2008af624a9c97/build-1.2.1-py3-none-any.whl", - "sha256": "75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__click": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", - "sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__colorama": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", - "sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__importlib_metadata": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl", - "sha256": "30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__installer": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl", - "sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__more_itertools": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/50/e2/8e10e465ee3987bb7c9ab69efb91d867d93959095f4807db102d07995d94/more_itertools-10.2.0-py3-none-any.whl", - "sha256": "686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__packaging": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", - "sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__pep517": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/25/6e/ca4a5434eb0e502210f591b97537d322546e4833dcb4d470a48c375c5540/pep517-0.13.1-py3-none-any.whl", - "sha256": "31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__pip": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl", - "sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__pip_tools": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl", - "sha256": "4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__pyproject_hooks": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/ae/f3/431b9d5fe7d14af7a32340792ef43b8a714e7726f1d7b69cc4e8e7a3f1d7/pyproject_hooks-1.1.0-py3-none-any.whl", - "sha256": "7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__setuptools": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl", - "sha256": "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__tomli": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", - "sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__wheel": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl", - "sha256": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - }, - "pypi__zipp": { - "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", - "attributes": { - "url": "https://files.pythonhosted.org/packages/da/55/a03fd7240714916507e1fcf7ae355bd9d9ed2e6db492595f1a67f61681be/zipp-3.18.2-py3-none-any.whl", - "sha256": "dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e", - "type": "zip", - "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" - } - } - } + }, + "recordedRepoMappingEntries": [ + [ + "rules_kotlin+", + "bazel_tools", + "bazel_tools" + ] + ] } }, "@@rules_python+//python/uv:uv.bzl%uv": { "general": { - "bzlTransitiveDigest": "ijW9KS7qsIY+yBVvJ+Nr1mzwQox09j13DnE3iIwaeTM=", - "usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=", - "recordedInputs": [ - "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", - "REPO_MAPPING:rules_python+,platforms platforms" - ], + "bzlTransitiveDigest": "8vT1ddXtljNxYD0tJkksqzeKE6xqx4Ix+tXthAppjTI=", + "usagesDigest": "WYhzIw9khRBy34H1GxV5+fI1yi07O90NmCXosPUdHWQ=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, "generatedRepoSpecs": { "uv": { "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo", @@ -255,7 +269,19 @@ "toolchain_target_settings": {} } } - } + }, + "recordedRepoMappingEntries": [ + [ + "rules_python+", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_python+", + "platforms", + "platforms" + ] + ] } } }, diff --git a/toolbelt/payload_buffer.cc b/toolbelt/payload_buffer.cc index 2b723d3..cf7a221 100644 --- a/toolbelt/payload_buffer.cc +++ b/toolbelt/payload_buffer.cc @@ -584,10 +584,13 @@ void *PayloadBuffer::Realloc(PayloadBuffer **buffer, void *p, uint32_t n, } // Need to free the old block and allocate a new one as the small block // index is different. + BufferOffset p_offset = (*buffer)->ToOffset(p); void *newp = Allocate(buffer, n, false, enable_small_block); if (newp == NULL) { return NULL; } + // Re-derive p since Allocate may have triggered a buffer resize. + p = (*buffer)->ToAddress(p_offset); memcpy(newp, p, decoded_length); if (clear && n > static_cast(decoded_length)) { memset(reinterpret_cast(newp) + decoded_length, 0, @@ -662,10 +665,13 @@ void *PayloadBuffer::Realloc(PayloadBuffer **buffer, void *p, uint32_t n, // one, copy the memory and free the old block. We are guaranteed that // the new block is larger than the original one since if it was smaller // we can always reuse the block. + BufferOffset p_offset = (*buffer)->ToOffset(p); void *newp = Allocate(buffer, n, false, enable_small_block); if (newp == NULL) { return NULL; } + // Re-derive p since Allocate may have triggered a buffer resize. + p = (*buffer)->ToAddress(p_offset); memcpy(newp, p, orig_length); if (clear) { memset(reinterpret_cast(newp) + orig_length, 0, n - orig_length); @@ -686,15 +692,14 @@ bool PayloadBuffer::PrimeBitmapAllocator(PayloadBuffer **self, size_t size) { return false; } (*self)->bitmaps[index] = offset; - VectorHeader *hdr = (*self)->ToAddress((*self)->bitmaps[index]); BitMapRun *run = PayloadBuffer::AllocateBitMapRun( self, bitmp_run_infos[index].size, bitmp_run_infos[index].num); if (run == nullptr) { return false; } - // Add to the vector, this might move the vector contents but the header - // will stay where it is. + // Re-derive hdr since AllocateBitMapRun may have triggered a buffer resize. + VectorHeader *hdr = (*self)->ToAddress((*self)->bitmaps[index]); (*self)->VectorPush(self, hdr, (*self)->ToOffset(run), false); return true; } @@ -742,8 +747,10 @@ void *BitMapRun::Allocate(PayloadBuffer **pb, int index, uint32_t, int size, } (*pb)->bitmaps[index] = offset; } - VectorHeader *hdr = (*pb)->ToAddress((*pb)->bitmaps[index]); for (;;) { + // Re-derive hdr each iteration since allocations below may trigger a + // buffer resize (realloc), invalidating any previous pointer. + VectorHeader *hdr = (*pb)->ToAddress((*pb)->bitmaps[index]); // Go backwards through the elements as that is most likely to find a free // bit. for (int i = hdr->num_elements - 1; i >= 0; i--) { @@ -781,8 +788,9 @@ void *BitMapRun::Allocate(PayloadBuffer **pb, int index, uint32_t, int size, if (run == nullptr) { return nullptr; } - // Add to the vector, this might move the vector contents but the header - // will stay where it is. + // Re-derive hdr since AllocateBitMapRun may have triggered a buffer + // resize, invalidating the previous pointer. + hdr = (*pb)->ToAddress((*pb)->bitmaps[index]); (*pb)->VectorPush(pb, hdr, (*pb)->ToOffset(run), false); } } diff --git a/toolbelt/payload_buffer.h b/toolbelt/payload_buffer.h index b25cdcb..08b1775 100644 --- a/toolbelt/payload_buffer.h +++ b/toolbelt/payload_buffer.h @@ -487,7 +487,6 @@ inline void PayloadBuffer::VectorPush(PayloadBuffer **self, VectorHeader *hdr, if (hdr->data == 0) { // The vector is empty, allocate it with a default size of 2. void *vecp = Allocate(self, 2 * sizeof(T), true, enable_small_block); - hdr->data = (*self)->ToOffset(vecp); VectorHeader *new_hdr = (*self)->ToAddress(hdr_offset); new_hdr->data = (*self)->ToOffset(vecp); hdr = new_hdr; diff --git a/toolbelt/payload_buffer_test.cc b/toolbelt/payload_buffer_test.cc index 52773fd..cd7d9db 100644 --- a/toolbelt/payload_buffer_test.cc +++ b/toolbelt/payload_buffer_test.cc @@ -11,7 +11,7 @@ using VectorHeader = toolbelt::VectorHeader; using Resizer = toolbelt::Resizer; TEST(BufferTest, Simple) { - char *buffer = (char *)malloc(4096); + char *buffer = (char *)calloc(1, 4096); PayloadBuffer *pb = new (buffer) PayloadBuffer(4096); pb->Dump(std::cout); toolbelt::Hexdump(pb, 64); @@ -25,7 +25,7 @@ TEST(BufferTest, Simple) { } TEST(BufferTest, TwoAllocs) { - char *buffer = (char *)malloc(4096); + char *buffer = (char *)calloc(1, 4096); PayloadBuffer *pb = new (buffer) PayloadBuffer(4096); pb->Dump(std::cout); toolbelt::Hexdump(pb, 64); @@ -45,7 +45,7 @@ TEST(BufferTest, TwoAllocs) { } TEST(BufferTest, Free) { - char *buffer = (char *)malloc(4096); + char *buffer = (char *)calloc(1, 4096); PayloadBuffer *pb = new (buffer) PayloadBuffer(4096); pb->Dump(std::cout); toolbelt::Hexdump(pb, 64); @@ -68,7 +68,7 @@ TEST(BufferTest, Free) { } TEST(BufferTest, FreeThenAlloc) { - char *buffer = (char *)malloc(4096); + char *buffer = (char *)calloc(1, 4096); PayloadBuffer *pb = new (buffer) PayloadBuffer(4096); pb->Dump(std::cout); toolbelt::Hexdump(pb, 64); @@ -95,7 +95,7 @@ TEST(BufferTest, FreeThenAlloc) { } TEST(BufferTest, SmallBlockAllocSimple) { - char *buffer = (char *)malloc(4096); + char *buffer = (char *)calloc(1, 4096); PayloadBuffer *pb = new (buffer) PayloadBuffer(4096); void *addr = PayloadBuffer::Allocate(&pb, 16); @@ -105,10 +105,13 @@ TEST(BufferTest, SmallBlockAllocSimple) { // Allocate again and make sure it's the same address. void *addr2 = PayloadBuffer::Allocate(&pb, 16); ASSERT_EQ(addr, addr2); + + pb->~PayloadBuffer(); + free(buffer); } TEST(BufferTest, SmallBlockAlloc) { - char *buffer = (char *)malloc(8192); + char *buffer = (char *)calloc(1, 8192); PayloadBuffer *pb = new (buffer) PayloadBuffer(8192); // Small block sizes are 16, 32, 64 and 128. @@ -137,10 +140,13 @@ TEST(BufferTest, SmallBlockAlloc) { } pb->Dump(std::cout); toolbelt::Hexdump(pb, pb->hwm); + + pb->~PayloadBuffer(); + free(buffer); } TEST(BufferTest, SmallBlockAllocFree) { - char *buffer = (char *)malloc(8192); + char *buffer = (char *)calloc(1, 8192); PayloadBuffer *pb = new (buffer) PayloadBuffer(8192); // Do a mix of sizes and free them. @@ -169,6 +175,9 @@ TEST(BufferTest, SmallBlockAllocFree) { } pb->Dump(std::cout); toolbelt::Hexdump(pb, pb->hwm); + + pb->~PayloadBuffer(); + free(buffer); } // This performance test compares the performance of the small block allocator @@ -186,7 +195,7 @@ TEST(BufferTest, BestCasePerformance) { constexpr int kIterations = 10000; for (int iter = 0; iter < kIterations; iter++) { - char *buffer = (char *)malloc(kSize); + char *buffer = (char *)calloc(1, kSize); PayloadBuffer *pb = new (buffer) PayloadBuffer(kSize); ASSERT_TRUE(PayloadBuffer::PrimeBitmapAllocator(&pb, 16)); @@ -231,7 +240,7 @@ TEST(BufferTest, BestCasePerformance) { // New buffer. free(buffer); - buffer = (char *)malloc(kSize); + buffer = (char *)calloc(1, kSize); pb = new (buffer) PayloadBuffer(kSize); // Now allocate by disabling the small block allocator. @@ -299,7 +308,7 @@ TEST(BufferTest, TypicalPerformance) { } for (int iter = 0; iter < kIterations; iter++) { - char *buffer = (char *)malloc(kSize); + char *buffer = (char *)calloc(1, kSize); PayloadBuffer *pb = new (buffer) PayloadBuffer(kSize); // No priming the small block allocator for this test. It probably won't @@ -329,7 +338,7 @@ TEST(BufferTest, TypicalPerformance) { // New buffer. free(buffer); - buffer = (char *)malloc(kSize); + buffer = (char *)calloc(1, kSize); pb = new (buffer) PayloadBuffer(kSize); // Switch off small block alloctor. @@ -365,7 +374,7 @@ TEST(BufferTest, TypicalPerformance) { TEST(BufferTest, Many) { constexpr size_t kSize = 8192; - char *buffer = (char *)malloc(kSize); + char *buffer = (char *)calloc(1, kSize); PayloadBuffer *pb = new (buffer) PayloadBuffer(kSize); std::vector addrs = PayloadBuffer::AllocateMany(&pb, 100, 10, true); @@ -387,7 +396,7 @@ TEST(BufferTest, Many) { } TEST(BufferTest, String) { - char *buffer = (char *)malloc(4096); + char *buffer = (char *)calloc(1, 4096); PayloadBuffer *pb = new (buffer) PayloadBuffer(4096); // Allocate space for a message containing an offset for the string. @@ -417,7 +426,7 @@ TEST(BufferTest, String) { } TEST(BufferTest, Vector) { - char *buffer = (char *)malloc(4096); + char *buffer = (char *)calloc(1, 4096); PayloadBuffer *pb = new (buffer) PayloadBuffer(4096); // Allocate space for a message containing the VectorHeader. @@ -439,7 +448,7 @@ TEST(BufferTest, Vector) { } TEST(BufferTest, VectorExpand) { - char *buffer = (char *)malloc(4096); + char *buffer = (char *)calloc(1, 4096); PayloadBuffer *pb = new (buffer) PayloadBuffer(4096); // Allocate space for a message containing the VectorHeader. @@ -466,7 +475,7 @@ TEST(BufferTest, VectorExpand) { } TEST(BufferTest, VectorExpandMore) { - char *buffer = (char *)malloc(4096); + char *buffer = (char *)calloc(1, 4096); PayloadBuffer *pb = new (buffer) PayloadBuffer(4096); // Allocate space for a message containing the VectorHeader. @@ -494,8 +503,123 @@ TEST(BufferTest, VectorExpandMore) { free(buffer); } +TEST(BufferTest, VectorPushWithResize) { + char *buffer = (char *)calloc(256, 1); + bool resized = false; + PayloadBuffer *pb = new (buffer) PayloadBuffer( + 256, [&resized, &buffer](PayloadBuffer **p, size_t, size_t new_size) { +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wclass-memaccess" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + *p = reinterpret_cast(realloc(*p, new_size)); +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + buffer = reinterpret_cast(*p); + resized = true; + }); + + PayloadBuffer::AllocateMainMessage(&pb, sizeof(VectorHeader)); + BufferOffset msg_offset = pb->message; + + constexpr int kCount = 200; + for (int i = 0; i < kCount; i++) { + VectorHeader *hdr = pb->ToAddress(msg_offset); + PayloadBuffer::VectorPush(&pb, hdr, i + 1); + } + ASSERT_TRUE(resized); + + VectorHeader *hdr = pb->ToAddress(msg_offset); + ASSERT_EQ(kCount, hdr->num_elements); + for (int i = 0; i < kCount; i++) { + uint32_t v = pb->VectorGet(hdr, i); + ASSERT_EQ(i + 1, v); + } + + pb->~PayloadBuffer(); + free(buffer); +} + +TEST(BufferTest, VectorReserveWithResize) { + char *buffer = (char *)calloc(256, 1); + bool resized = false; + PayloadBuffer *pb = new (buffer) PayloadBuffer( + 256, [&resized, &buffer](PayloadBuffer **p, size_t, size_t new_size) { +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wclass-memaccess" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + *p = reinterpret_cast(realloc(*p, new_size)); +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + buffer = reinterpret_cast(*p); + resized = true; + }); + + PayloadBuffer::AllocateMainMessage(&pb, sizeof(VectorHeader)); + BufferOffset msg_offset = pb->message; + + VectorHeader *hdr = pb->ToAddress(msg_offset); + PayloadBuffer::VectorReserve(&pb, hdr, 500); + ASSERT_TRUE(resized); + + hdr = pb->ToAddress(msg_offset); + ASSERT_NE(0u, hdr->data); + + pb->~PayloadBuffer(); + free(buffer); +} + +TEST(BufferTest, VectorResizeWithResize) { + char *buffer = (char *)calloc(256, 1); + bool resized = false; + PayloadBuffer *pb = new (buffer) PayloadBuffer( + 256, [&resized, &buffer](PayloadBuffer **p, size_t, size_t new_size) { +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wclass-memaccess" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + *p = reinterpret_cast(realloc(*p, new_size)); +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + buffer = reinterpret_cast(*p); + resized = true; + }); + + PayloadBuffer::AllocateMainMessage(&pb, sizeof(VectorHeader)); + BufferOffset msg_offset = pb->message; + + VectorHeader *hdr = pb->ToAddress(msg_offset); + PayloadBuffer::VectorResize(&pb, hdr, 500); + ASSERT_TRUE(resized); + + hdr = pb->ToAddress(msg_offset); + ASSERT_EQ(500u, hdr->num_elements); + + pb->~PayloadBuffer(); + free(buffer); +} + TEST(BufferTest, Resizeable) { - char *buffer = (char *)malloc(512); + char *buffer = (char *)calloc(1, 512); bool resized = false; PayloadBuffer *pb = new (buffer) PayloadBuffer( 256, [&resized](PayloadBuffer **p, size_t, size_t new_size) { @@ -537,7 +661,11 @@ TEST(BufferTest, Resizeable) { toolbelt::Hexdump(pb, pb->hwm); // Don't free 'buffer' as it has already been freed by the call to realloc. - delete pb; + // pb was constructed via placement-new on a malloc/realloc'd buffer, so we + // must invoke the destructor explicitly and then free() the storage rather + // than calling operator delete (which would be an alloc-dealloc mismatch). + pb->~PayloadBuffer(); + free(pb); } int main(int argc, char **argv) { diff --git a/toolbelt/pipe_test.cc b/toolbelt/pipe_test.cc index d0d5811..30be8a5 100644 --- a/toolbelt/pipe_test.cc +++ b/toolbelt/pipe_test.cc @@ -6,6 +6,7 @@ #include "co/coroutine.h" #include "pipe.h" #include +#include #define VAR(a) a##__COUNTER__ #define EVAL_AND_ASSERT_OK(expr) EVAL_AND_ASSERT_OK2(VAR(r_), expr) @@ -69,7 +70,7 @@ TEST(PipeTest, CoroutinePipeReadAndWrite) { auto r = pipe.Read(buffer, 5, c); ASSERT_OK(r); ASSERT_EQ(*r, 5); - ASSERT_STREQ(buffer, "Hello"); + ASSERT_EQ(std::string_view(buffer, *r), "Hello"); }); co::Coroutine writer(scheduler, [&pipe](co::Coroutine *c) { const char *msg = "Hello"; @@ -92,7 +93,7 @@ TEST(PipeTest, CoroutinePipeReadAndWriteNonblocking) { auto r = pipe.Read(buffer, 5, c); ASSERT_OK(r); ASSERT_EQ(*r, 5); - ASSERT_STREQ(buffer, "Hello"); + ASSERT_EQ(std::string_view(buffer, *r), "Hello"); }); co::Coroutine writer(scheduler, [&pipe](co::Coroutine *c) { const char *msg = "Hello"; @@ -158,7 +159,7 @@ TEST(PipeTest, CoroutineFullPipeReadAndWrite) { auto r = pipe.Read(buffer, kMessageSize, c); ASSERT_OK(r); ASSERT_EQ(*r, kMessageSize); - ASSERT_STREQ(buffer, "1234"); + ASSERT_EQ(std::string_view(buffer, *r), "1234"); } }); co::Coroutine writer(scheduler, [&pipe, kMessageSize](co::Coroutine *c) { @@ -174,6 +175,10 @@ TEST(PipeTest, CoroutineFullPipeReadAndWrite) { } TEST(PipeTest, CoroutineOverFullPipeReadAndWrite) { +#if defined(THREAD_SANITIZER) + GTEST_SKIP() << "TSan + many coroutine fiber switches in this stress test " + "trips a known TSan runtime issue (nested DEADLYSIGNAL)."; +#endif co::CoroutineScheduler scheduler; auto p = toolbelt::Pipe::Create(); ASSERT_OK(p); @@ -189,7 +194,7 @@ TEST(PipeTest, CoroutineOverFullPipeReadAndWrite) { auto r = pipe.Read(buffer, kMessageSize, c); ASSERT_OK(r); ASSERT_EQ(*r, kMessageSize); - ASSERT_STREQ(buffer, "1234"); + ASSERT_EQ(std::string_view(buffer, *r), "1234"); } }); co::Coroutine writer(scheduler, [&pipe, kMessageSize](co::Coroutine *c) { @@ -221,7 +226,7 @@ TEST(PipeTest, CoroutineFullPipeReadAndWriteNonblocking) { auto r = pipe.Read(buffer, kMessageSize, c); ASSERT_OK(r); ASSERT_EQ(*r, kMessageSize); - ASSERT_STREQ(buffer, "1234"); + ASSERT_EQ(std::string_view(buffer, *r), "1234"); } }); co::Coroutine writer(scheduler, [&pipe, kMessageSize](co::Coroutine *c) { @@ -237,6 +242,10 @@ TEST(PipeTest, CoroutineFullPipeReadAndWriteNonblocking) { } TEST(PipeTest, CoroutineOverFullPipeReadAndWriteNonblocking) { +#if defined(THREAD_SANITIZER) + GTEST_SKIP() << "TSan + many coroutine fiber switches in this stress test " + "trips a known TSan runtime issue (nested DEADLYSIGNAL)."; +#endif co::CoroutineScheduler scheduler; auto p = toolbelt::Pipe::Create(); ASSERT_OK(p); @@ -253,7 +262,7 @@ TEST(PipeTest, CoroutineOverFullPipeReadAndWriteNonblocking) { auto r = pipe.Read(buffer, kMessageSize, c); ASSERT_OK(r); ASSERT_EQ(*r, kMessageSize); - ASSERT_STREQ(buffer, "1234"); + ASSERT_EQ(std::string_view(buffer, *r), "1234"); } }); co::Coroutine writer(scheduler, [&pipe, kMessageSize](co::Coroutine *c) { @@ -279,12 +288,12 @@ TEST(PipeTest, CoroutinePipeReadAndMultiWrite) { auto r = pipe.Read(buffer, 5, c); ASSERT_OK(r); ASSERT_EQ(*r, 5); - ASSERT_STREQ(buffer, "12345"); + ASSERT_EQ(std::string_view(buffer, *r), "12345"); r = pipe.Read(buffer, 5, c); ASSERT_OK(r); ASSERT_EQ(*r, 5); - ASSERT_STREQ(buffer, "54321"); + ASSERT_EQ(std::string_view(buffer, *r), "54321"); }); co::Coroutine writer1(scheduler, [&pipe](co::Coroutine *c) { @@ -304,6 +313,10 @@ TEST(PipeTest, CoroutinePipeReadAndMultiWrite) { } TEST(PipeTest, CoroutineOverFullPipeReadAndWriteMultiwriter) { +#if defined(THREAD_SANITIZER) + GTEST_SKIP() << "TSan + many coroutine fiber switches in this stress test " + "trips a known TSan runtime issue (nested DEADLYSIGNAL)."; +#endif co::CoroutineScheduler scheduler; auto p = toolbelt::Pipe::Create(); ASSERT_OK(p); @@ -320,7 +333,8 @@ TEST(PipeTest, CoroutineOverFullPipeReadAndWriteMultiwriter) { ASSERT_OK(r); ASSERT_EQ(*r, kMessageSize); // Can be in either order. - bool ok = (strcmp(buffer, "1234") == 0) || (strcmp(buffer, "4321") == 0); + std::string_view got(buffer, *r); + bool ok = got == "1234" || got == "4321"; ASSERT_TRUE(ok); } }); @@ -347,6 +361,10 @@ TEST(PipeTest, CoroutineOverFullPipeReadAndWriteMultiwriter) { TEST(PipeTest, CoroutineOverFullPipeReadAndWriteMultiwriterNonblocking) { +#if defined(THREAD_SANITIZER) + GTEST_SKIP() << "TSan + many coroutine fiber switches in this stress test " + "trips a known TSan runtime issue (nested DEADLYSIGNAL)."; +#endif co::CoroutineScheduler scheduler; auto p = toolbelt::Pipe::Create(); ASSERT_OK(p); @@ -364,7 +382,8 @@ TEST(PipeTest, CoroutineOverFullPipeReadAndWriteMultiwriterNonblocking) { ASSERT_OK(r); ASSERT_EQ(*r, kMessageSize); // Can be in either order. - bool ok = (strcmp(buffer, "1234") == 0) || (strcmp(buffer, "4321") == 0); + std::string_view got(buffer, *r); + bool ok = got == "1234" || got == "4321"; ASSERT_TRUE(ok); } }); diff --git a/toolbelt/sockets_test.cc b/toolbelt/sockets_test.cc index 08c253c..24532ae 100644 --- a/toolbelt/sockets_test.cc +++ b/toolbelt/sockets_test.cc @@ -512,11 +512,14 @@ TEST(SocketsTest, UDPSocket_SendAndReceiveUnicast) { std::vector Receive_buffer(TEST_DATA.size()); ASSERT_EQ(*Receiver.Receive(Receive_buffer.data(), Receive_buffer.size()), TEST_DATA.size()); ASSERT_EQ(std::string_view(Receive_buffer.data(), Receive_buffer.size()), TEST_DATA); - - ASSERT_EQ(0, std::strcmp(Receive_buffer.data(), TEST_DATA.data())); } TEST(SocketsTest, UDPSocket_SendAndReceiveBroadcast) { +#if defined(__APPLE__) + GTEST_SKIP() << "UDP broadcast to 255.255.255.255 over loopback is not " + "permitted in the GitHub Actions macOS runner network " + "sandbox; skip on macOS."; +#endif UnusedPort port; auto sender = toolbelt::UDPSocket(); auto Receiver = toolbelt::UDPSocket(); @@ -532,11 +535,14 @@ TEST(SocketsTest, UDPSocket_SendAndReceiveBroadcast) { std::vector Receive_buffer(TEST_DATA.size()); ASSERT_EQ(*Receiver.Receive(Receive_buffer.data(), Receive_buffer.size()), TEST_DATA.size()); ASSERT_EQ(std::string_view(Receive_buffer.data(), Receive_buffer.size()), TEST_DATA); - - ASSERT_EQ(0, std::strcmp(Receive_buffer.data(), TEST_DATA.data())); } TEST(SocketsTest, UDPSocket_SendAndReceiveMulticast) { +#if defined(__APPLE__) + GTEST_SKIP() << "UDP multicast over loopback is not reliably available in " + "the GitHub Actions macOS runner network sandbox; skip on " + "macOS."; +#endif UnusedPort port; std::string multicast_ip = "224.0.0.205"; toolbelt::InetAddress multicast_address(multicast_ip, port);