cargo-subunit-0.1.3/.cargo_vcs_info.json0000644000000001361046102023000136410ustar { "git": { "sha1": "e96eed37531b5c8d5abebece9eff9750eaeecc95" }, "path_in_vcs": "" }cargo-subunit-0.1.3/.github/CODEOWNERS000064400000000000000000000000121046102023000153330ustar 00000000000000* @jelmer cargo-subunit-0.1.3/.github/FUNDING.yml000064400000000000000000000000171046102023000155620ustar 00000000000000github: jelmer cargo-subunit-0.1.3/.github/dependabot.yml000064400000000000000000000006251046102023000166020ustar 00000000000000# Please see the documentation for all configuration options: # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "cargo" directory: "/" schedule: interval: "weekly" rebase-strategy: "disabled" - package-ecosystem: "github-actions" directory: "/" schedule: interval: weekly cargo-subunit-0.1.3/.github/workflows/auto-merge.yaml000064400000000000000000000011341046102023000207340ustar 00000000000000name: Dependabot auto-merge on: pull_request_target permissions: pull-requests: write contents: write jobs: dependabot: runs-on: ubuntu-latest if: ${{ github.actor == 'dependabot[bot]' }} steps: - name: Dependabot metadata id: metadata uses: dependabot/fetch-metadata@v3 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Enable auto-merge for Dependabot PRs run: gh pr merge --auto --squash "$PR_URL" env: PR_URL: ${{github.event.pull_request.html_url}} GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} cargo-subunit-0.1.3/.github/workflows/rust.yml000064400000000000000000000007241046102023000175270ustar 00000000000000--- name: Rust "on": push: pull_request: env: CARGO_TERM_COLOR: always jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest] fail-fast: false steps: - uses: actions/checkout@v6 - name: Build run: cargo build --verbose env: RUSTFLAGS: -Dwarnings - name: Run tests run: cargo test --verbose env: RUSTFLAGS: -Dwarnings cargo-subunit-0.1.3/.gitignore000064400000000000000000000000121046102023000143700ustar 00000000000000target *~ cargo-subunit-0.1.3/Cargo.lock0000644000000650241046102023000116230ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anstream" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", "windows-sys", ] [[package]] name = "anyhow" version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "async-stream" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", "pin-project-lite", ] [[package]] name = "async-stream-impl" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "async-trait" version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "bumpalo" version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cargo-subunit" version = "0.1.3" dependencies = [ "anyhow", "chrono", "clap", "serde", "serde_json", "subunit", "tempfile", ] [[package]] name = "cc" version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-link", ] [[package]] name = "clap" version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_derive" version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", "quote", "syn", ] [[package]] name = "clap_lex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "colorchoice" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "crc32fast" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "darling" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ "darling_core", "darling_macro", ] [[package]] name = "darling_core" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "syn", ] [[package]] name = "darling_macro" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", "syn", ] [[package]] name = "enumset" version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" dependencies = [ "darling", "proc-macro2", "quote", "syn", ] [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys", ] [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "find-msvc-tools" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "futures-core" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "getrandom" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", "r-efi", "wasip2", "wasip3", ] [[package]] name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash", ] [[package]] name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "iana-time-zone" version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "log", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "id-arena" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", "serde", "serde_core", ] [[package]] name = "is_terminal_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itoa" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "leb128fmt" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "linux-raw-sys" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "lock_api" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ "scopeguard", ] [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "mio" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "wasi", "windows-sys", ] [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "parking_lot" version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-link", ] [[package]] name = "pin-project-lite" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "prettyplease" version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "rustversion" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", ] [[package]] name = "serde_core" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", "serde", "serde_core", "zmij", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ "errno", "libc", ] [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", "windows-sys", ] [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subunit" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5e04a231485ceb8501d711032d1b569d3956f6a062fe8b08df1ae2c96b0cf2e" dependencies = [ "async-stream", "async-trait", "chrono", "crc32fast", "enumset", "thiserror", "tokio", "tokio-stream", ] [[package]] name = "syn" version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tempfile" version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "getrandom", "once_cell", "rustix", "windows-sys", ] [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tokio" version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", "windows-sys", ] [[package]] name = "tokio-macros" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tokio-stream" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", "tokio", ] [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasip3" version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-encoder" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" dependencies = [ "leb128fmt", "wasmparser", ] [[package]] name = "wasm-metadata" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", "indexmap", "wasm-encoder", "wasmparser", ] [[package]] name = "wasmparser" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", "hashbrown 0.15.5", "indexmap", "semver", ] [[package]] name = "windows-core" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-interface" version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ "windows-link", ] [[package]] name = "windows-sys" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] [[package]] name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" dependencies = [ "wit-bindgen-rust-macro", ] [[package]] name = "wit-bindgen-core" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ "anyhow", "heck", "wit-parser", ] [[package]] name = "wit-bindgen-rust" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck", "indexmap", "prettyplease", "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", ] [[package]] name = "wit-bindgen-rust-macro" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" dependencies = [ "anyhow", "prettyplease", "proc-macro2", "quote", "syn", "wit-bindgen-core", "wit-bindgen-rust", ] [[package]] name = "wit-component" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags", "indexmap", "log", "serde", "serde_derive", "serde_json", "wasm-encoder", "wasm-metadata", "wasmparser", "wit-parser", ] [[package]] name = "wit-parser" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", "indexmap", "log", "semver", "serde", "serde_derive", "serde_json", "unicode-xid", "wasmparser", ] [[package]] name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" cargo-subunit-0.1.3/Cargo.toml0000644000000024371046102023000116450ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "cargo-subunit" version = "0.1.3" authors = ["Jelmer Vernooij "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Cargo extension to run tests and output results in subunit format" readme = "README.md" license = "Apache-2.0" repository = "https://github.com/jelmer/cargo-subunit" [[bin]] name = "cargo-subunit" path = "src/main.rs" [[test]] name = "integration" path = "tests/integration.rs" [dependencies.anyhow] version = "1.0" [dependencies.chrono] version = "0.4" [dependencies.clap] version = "4.6" features = ["derive"] [dependencies.serde] version = "1.0" features = ["derive"] [dependencies.serde_json] version = "1.0" [dependencies.subunit] version = "0.3" [dev-dependencies.tempfile] version = "3.26" cargo-subunit-0.1.3/Cargo.toml.orig000064400000000000000000000010461046102023000152770ustar 00000000000000[package] name = "cargo-subunit" version = "0.1.3" edition = "2021" authors = ["Jelmer Vernooij "] description = "Cargo extension to run tests and output results in subunit format" license = "Apache-2.0" repository = "https://github.com/jelmer/cargo-subunit" [[bin]] name = "cargo-subunit" path = "src/main.rs" [dependencies] subunit = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" chrono = "0.4" clap = { version = "4.6", features = ["derive"] } anyhow = "1.0" [dev-dependencies] tempfile = "3.26" cargo-subunit-0.1.3/README.md000064400000000000000000000051571046102023000136760ustar 00000000000000# cargo-subunit A Cargo extension that runs Rust tests and outputs results in [subunit v2](https://github.com/testing-cabal/subunit) format. ## Features - **List tests**: Display all available tests with unique namespaces - **Run tests**: Execute tests and stream results in subunit format - **Load test list**: Run specific tests from a file - **Standard cargo test args**: Forward any cargo test arguments ## Installation ```bash cargo install --path . ``` ## Usage ### List all available tests ```bash cargo subunit --list ``` This outputs test names in subunit v2 format using "exists" events. Each test is identified by its fully-qualified name (e.g., `module::submodule::test_name`). The output can be consumed by subunit tools or testrepository. ### Run all tests with subunit output ```bash cargo subunit ``` The subunit v2 binary output is written to stdout. You can redirect it to a file: ```bash cargo subunit > results.subunit ``` ### Run specific tests Pass test filters just like with `cargo test`: ```bash cargo subunit test_name cargo subunit module:: ``` ### Run tests from a file Create a file with test names (one per line): ```bash echo "module::test_one" > tests.txt echo "module::test_two" >> tests.txt cargo subunit --load-list tests.txt ``` ### Pass additional cargo test arguments Any arguments after `--` are forwarded to cargo test: ```bash cargo subunit -- --nocapture cargo subunit -- --test-threads=1 ``` ## Integration with testrepository cargo-subunit integrates seamlessly with [testrepository](https://testrepository.readthedocs.io/) for tracking test history and running tests efficiently. Create a `.testr.conf` file in your project root: ```ini [DEFAULT] test_command=cargo subunit $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list ``` Then you can use testrepository commands: ```bash # Run all tests and record results testr run # Run only failed tests from the last run testr run --failing # List test runs testr last # Show results from the last run testr last --subunit | subunit-stats ``` ## How it works cargo-subunit uses cargo test's unstable JSON output format (enabled via `RUSTC_BOOTSTRAP=1`) to capture test events, then converts them to subunit v2 format. **For `--list` mode:** - Each test generates an `exists` event with the test ID **For running tests:** 1. An `inprogress` event when the test starts 2. A `success`, `fail`, `skip`, or `fail` (timeout) event when complete 3. For failures, stdout/stderr are attached as file content ## Requirements - Rust 2021 edition or later - The `subunit` crate for protocol serialization ## License Apache-2.0 cargo-subunit-0.1.3/src/json_parser.rs000064400000000000000000000112151046102023000160710ustar 00000000000000use anyhow::{Context, Result}; use serde::Deserialize; /// Events we care about from cargo test JSON output #[derive(Debug, Clone)] pub enum TestEvent { /// A test has started Started { name: String }, /// A test passed Passed { name: String, #[allow(dead_code)] duration_secs: Option, }, /// A test failed Failed { name: String, #[allow(dead_code)] duration_secs: Option, stdout: Option, stderr: Option, }, /// A test was ignored/skipped Ignored { name: String }, /// A test timed out Timeout { name: String, #[allow(dead_code)] duration_secs: Option, }, } /// Top-level JSON event from cargo test #[derive(Debug, Deserialize)] #[serde(tag = "type", rename_all = "lowercase")] enum JsonEvent { Suite { #[allow(dead_code)] event: String, #[serde(default)] #[allow(dead_code)] test_count: Option, }, Test { event: String, name: String, #[serde(default)] exec_time: Option, #[serde(default)] stdout: Option, #[serde(default)] stderr: Option, }, } /// Parse a JSON line from cargo test output pub fn parse_event(line: &str) -> Result> { let json_event: JsonEvent = serde_json::from_str(line).context("Failed to parse JSON event")?; match json_event { JsonEvent::Suite { .. } => { // We don't emit events for suite start/end Ok(None) } JsonEvent::Test { event, name, exec_time, stdout, stderr, } => { let test_event = match event.as_str() { "started" => TestEvent::Started { name }, "ok" => TestEvent::Passed { name, duration_secs: exec_time, }, "failed" => TestEvent::Failed { name, duration_secs: exec_time, stdout, stderr, }, "ignored" => TestEvent::Ignored { name }, "timeout" => TestEvent::Timeout { name, duration_secs: exec_time, }, _ => { // Unknown test event, skip return Ok(None); } }; Ok(Some(test_event)) } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_parse_suite_started() { let line = r#"{"type":"suite","event":"started","test_count":3}"#; let event = parse_event(line).unwrap(); assert!(event.is_none()); } #[test] fn test_parse_test_started() { let line = r#"{"type":"test","event":"started","name":"my_test"}"#; let event = parse_event(line).unwrap().unwrap(); match event { TestEvent::Started { name } => assert_eq!(name, "my_test"), _ => panic!("Expected Started event"), } } #[test] fn test_parse_test_passed() { let line = r#"{"type":"test","event":"ok","name":"my_test","exec_time":0.001}"#; let event = parse_event(line).unwrap().unwrap(); match event { TestEvent::Passed { name, duration_secs, } => { assert_eq!(name, "my_test"); assert_eq!(duration_secs, Some(0.001)); } _ => panic!("Expected Passed event"), } } #[test] fn test_parse_test_failed() { let line = r#"{"type":"test","event":"failed","name":"my_test","exec_time":0.002,"stdout":"output","stderr":"error"}"#; let event = parse_event(line).unwrap().unwrap(); match event { TestEvent::Failed { name, duration_secs, stdout, stderr, } => { assert_eq!(name, "my_test"); assert_eq!(duration_secs, Some(0.002)); assert_eq!(stdout, Some("output".to_string())); assert_eq!(stderr, Some("error".to_string())); } _ => panic!("Expected Failed event"), } } #[test] fn test_parse_test_ignored() { let line = r#"{"type":"test","event":"ignored","name":"my_test"}"#; let event = parse_event(line).unwrap().unwrap(); match event { TestEvent::Ignored { name } => assert_eq!(name, "my_test"), _ => panic!("Expected Ignored event"), } } } cargo-subunit-0.1.3/src/main.rs000064400000000000000000000135521046102023000144760ustar 00000000000000use anyhow::{Context, Result}; use clap::Parser; use std::io::{BufRead, BufReader}; use std::process::{Command, Stdio}; mod json_parser; mod subunit_writer; use subunit_writer::SubunitWriter; #[derive(Parser, Debug)] #[command( name = "cargo-subunit", about = "Run Rust tests and output results in subunit format", bin_name = "cargo" )] struct Cli { /// Cargo subcommand name (always "subunit") #[arg(value_name = "subunit", hide = true)] _subcommand: Option, /// List all available tests without running them #[command(flatten)] mode: Mode, /// Additional arguments to pass to cargo test #[arg(trailing_var_arg = true, allow_hyphen_values = true)] cargo_args: Vec, } #[derive(Parser, Debug)] #[group(multiple = false)] struct Mode { /// List all available tests without running them #[arg(long)] list: bool, /// Load test names from a file (one per line) and run only those tests #[arg(long, value_name = "FILE")] load_list: Option, } fn main() -> Result<()> { let cli = Cli::parse(); if cli.mode.list { list_tests(&cli.cargo_args) } else if let Some(load_list_file) = &cli.mode.load_list { run_tests_from_file(load_list_file, &cli.cargo_args) } else { run_tests(&cli.cargo_args) } } /// List all available tests fn list_tests(cargo_args: &[String]) -> Result<()> { let mut cmd = Command::new("cargo"); cmd.arg("test"); cmd.args(cargo_args); cmd.args(["--", "--list", "--format", "terse"]); // Capture stdout (we parse it for test names) but inherit stderr so the // user sees the build progress live — without this, listing a fresh // workspace looks frozen for the duration of the compile. cmd.stdout(Stdio::piped()); cmd.stderr(Stdio::inherit()); let mut child = cmd.spawn().context("Failed to run cargo test --list")?; let stdout = child .stdout .take() .context("Failed to capture cargo test --list stdout")?; let reader = BufReader::new(stdout); let mut writer = SubunitWriter::new(std::io::stdout()); // Parse test names and write as subunit "exists" events for line in reader.lines() { let line = line.context("Failed to read cargo test --list output")?; let line = line.trim(); // Skip empty lines and the summary line if line.is_empty() || line.ends_with(" tests, ") || line.contains(" benchmarks") { continue; } // Remove ": test" or ": bench" suffix let test_name = if let Some(name) = line.strip_suffix(": test") { name } else if let Some(name) = line.strip_suffix(": bench") { name } else { // Fallback: use as-is line }; // Write an "exists" event for this test writer.write_test_exists(test_name)?; } let status = child .wait() .context("Failed to wait for cargo test --list")?; if !status.success() { anyhow::bail!("cargo test --list failed with exit code: {}", status); } Ok(()) } /// Run tests specified in a file fn run_tests_from_file(file_path: &str, cargo_args: &[String]) -> Result<()> { let file = std::fs::File::open(file_path) .context(format!("Failed to open test list file: {}", file_path))?; let reader = BufReader::new(file); let test_names: Vec = reader .lines() .collect::, _>>() .context("Failed to read test names from file")? .into_iter() .map(|line| line.trim().to_string()) .filter(|line| !line.is_empty()) .collect(); if test_names.is_empty() { anyhow::bail!("No test names found in file: {}", file_path); } run_tests_with_filters(&test_names, cargo_args) } /// Run tests with optional test name filters fn run_tests_with_filters(test_filters: &[String], cargo_args: &[String]) -> Result<()> { let mut cmd = Command::new("cargo"); cmd.arg("test"); cmd.args(cargo_args); // Add unstable JSON output flags cmd.args([ "--", "-Z", "unstable-options", "--format", "json", "--report-time", ]); // Add test filters for filter in test_filters { cmd.arg(filter); } // Enable unstable features on stable Rust cmd.env("RUSTC_BOOTSTRAP", "1"); // Capture stdout for parsing cmd.stdout(Stdio::piped()); cmd.stderr(Stdio::inherit()); let mut child = cmd.spawn().context("Failed to spawn cargo test")?; let stdout = child.stdout.take().context("Failed to capture stdout")?; let reader = BufReader::new(stdout); let mut writer = SubunitWriter::new(std::io::stdout()); // Process JSON events line by line for line in reader.lines() { let line = line.context("Failed to read line from cargo test output")?; let trimmed = line.trim(); // Skip empty lines and non-JSON lines (cargo test outputs build messages, etc.) if trimmed.is_empty() || !trimmed.starts_with('{') { continue; } match json_parser::parse_event(&line) { Ok(Some(event)) => { writer.write_event(&event)?; } Ok(None) => { // Non-test event (e.g., suite events), skip } Err(e) => { // JSON parsing failure is fatal eprintln!("Error: Failed to parse JSON event: {}", e); eprintln!("JSON: {}", line); anyhow::bail!("Failed to parse cargo test JSON output"); } } } let status = child.wait().context("Failed to wait for cargo test")?; if !status.success() { std::process::exit(status.code().unwrap_or(1)); } Ok(()) } /// Run all tests fn run_tests(cargo_args: &[String]) -> Result<()> { run_tests_with_filters(&[], cargo_args) } cargo-subunit-0.1.3/src/subunit_writer.rs000064400000000000000000000127531046102023000166410ustar 00000000000000use anyhow::Result; use chrono::Utc; use std::io::Write; use subunit::serialize::Serializable; use subunit::types::event::Event; use subunit::types::teststatus::TestStatus; use crate::json_parser::TestEvent; /// Writer that converts test events to subunit format pub struct SubunitWriter { output: W, } impl SubunitWriter { /// Create a new subunit writer pub fn new(output: W) -> Self { Self { output } } /// Write a test event in subunit format pub fn write_event(&mut self, event: &TestEvent) -> Result<()> { let evt = match event { TestEvent::Started { name } => Event::new(TestStatus::InProgress) .test_id(name) .datetime(Utc::now()) .map_err(|e| anyhow::anyhow!("Failed to create timestamp: {}", e))? .build(), TestEvent::Passed { name, duration_secs: _, } => Event::new(TestStatus::Success) .test_id(name) .datetime(Utc::now()) .map_err(|e| anyhow::anyhow!("Failed to create timestamp: {}", e))? .build(), TestEvent::Failed { name, duration_secs: _, stdout, stderr, } => { let mut builder = Event::new(TestStatus::Failed) .test_id(name) .datetime(Utc::now()) .map_err(|e| anyhow::anyhow!("Failed to create timestamp: {}", e))?; // Note: subunit v2 allows only one file attachment per event // If both stdout and stderr exist, we prefer stderr (more important for failures) if let Some(stdout_content) = stdout { if !stdout_content.is_empty() { builder = builder .mime_type("text/plain;charset=utf8") .file_content("stdout", stdout_content.as_bytes()); } } if let Some(stderr_content) = stderr { if !stderr_content.is_empty() { builder = builder .mime_type("text/plain;charset=utf8") .file_content("stderr", stderr_content.as_bytes()); } } builder.build() } TestEvent::Ignored { name } => Event::new(TestStatus::Skipped) .test_id(name) .datetime(Utc::now()) .map_err(|e| anyhow::anyhow!("Failed to create timestamp: {}", e))? .build(), TestEvent::Timeout { name, duration_secs: _, } => Event::new(TestStatus::Failed) .test_id(name) .datetime(Utc::now()) .map_err(|e| anyhow::anyhow!("Failed to create timestamp: {}", e))? .mime_type("text/plain;charset=utf8") .file_content("reason", b"Test timed out") .build(), }; evt.serialize(&mut self.output) .map_err(|e| anyhow::anyhow!("Failed to write subunit event: {}", e))?; // Flush after each event to ensure real-time output self.output.flush()?; Ok(()) } /// Write a test existence event (for --list mode) pub fn write_test_exists(&mut self, test_name: &str) -> Result<()> { let evt = Event::new(TestStatus::Enumeration) .test_id(test_name) .datetime(Utc::now()) .map_err(|e| anyhow::anyhow!("Failed to create timestamp: {}", e))? .build(); evt.serialize(&mut self.output) .map_err(|e| anyhow::anyhow!("Failed to write subunit event: {}", e))?; // Flush after each event to ensure real-time output self.output.flush()?; Ok(()) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_write_started_event() { let mut output = Vec::new(); let mut writer = SubunitWriter::new(&mut output); writer .write_event(&TestEvent::Started { name: "my_test".to_string(), }) .unwrap(); // Just verify that something was written assert!(!output.is_empty()); } #[test] fn test_write_passed_event() { let mut output = Vec::new(); let mut writer = SubunitWriter::new(&mut output); writer .write_event(&TestEvent::Passed { name: "my_test".to_string(), duration_secs: Some(0.5), }) .unwrap(); assert!(!output.is_empty()); } #[test] fn test_write_failed_event() { let mut output = Vec::new(); let mut writer = SubunitWriter::new(&mut output); writer .write_event(&TestEvent::Failed { name: "my_test".to_string(), duration_secs: Some(0.5), stdout: Some("test output".to_string()), stderr: Some("error message".to_string()), }) .unwrap(); assert!(!output.is_empty()); } #[test] fn test_write_ignored_event() { let mut output = Vec::new(); let mut writer = SubunitWriter::new(&mut output); writer .write_event(&TestEvent::Ignored { name: "my_test".to_string(), }) .unwrap(); assert!(!output.is_empty()); } } cargo-subunit-0.1.3/tests/integration.rs000064400000000000000000000041261046102023000164450ustar 00000000000000use std::io::Write; use std::process::Command; use tempfile::NamedTempFile; #[test] fn test_list_tests() { // Run cargo-subunit --list on this project itself let output = Command::new("cargo") .args(&["run", "--", "--list"]) .current_dir(env!("CARGO_MANIFEST_DIR")) .output() .expect("Failed to run cargo-subunit --list"); assert!(output.status.success(), "cargo-subunit --list failed"); let stdout = output.stdout; // Should output subunit v2 format assert!(!stdout.is_empty(), "Expected subunit output"); assert_eq!(stdout[0], 0xb3, "Expected subunit v2 signature byte"); } #[test] fn test_run_tests_with_subunit_output() { // Run cargo-subunit on this project itself let output = Command::new("cargo") .args(&["run", "--"]) .current_dir(env!("CARGO_MANIFEST_DIR")) .output() .expect("Failed to run cargo-subunit"); // The command might fail if tests fail, but we should get some output let stdout = output.stdout; // Subunit v2 packets start with signature 0xb3 assert!(!stdout.is_empty(), "Expected subunit output"); assert_eq!(stdout[0], 0xb3, "Expected subunit v2 signature byte"); } #[test] fn test_load_list_functionality() { // Create a temporary file with a test name let mut temp_file = NamedTempFile::new().expect("Failed to create temp file"); writeln!(temp_file, "json_parser::tests::test_parse_suite_started") .expect("Failed to write to temp file"); let temp_path = temp_file.path().to_str().unwrap(); // Run cargo-subunit with --load-list let output = Command::new("cargo") .args(&["run", "--", "--load-list", temp_path]) .current_dir(env!("CARGO_MANIFEST_DIR")) .output() .expect("Failed to run cargo-subunit --load-list"); // Should succeed assert!(output.status.success(), "cargo-subunit --load-list failed"); let stdout = output.stdout; // Should have subunit output assert!(!stdout.is_empty(), "Expected subunit output"); assert_eq!(stdout[0], 0xb3, "Expected subunit v2 signature byte"); }