Merge branch 'master' into pr

This commit is contained in:
Terts Diepraam 2021-05-31 15:23:06 +02:00
commit 7690dc018f
76 changed files with 1318 additions and 938 deletions

View file

@ -84,7 +84,7 @@ jobs:
- name: Install `rust` toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: nightly
default: true
profile: minimal # minimal component installation (ie, no documentation)
components: clippy
@ -94,7 +94,7 @@ jobs:
run: |
# `clippy` testing
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
S=$(cargo clippy ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -- -D warnings 2>&1) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*$/::warning file=\2,line=\3,col=\4::WARNING: \`cargo clippy\`: \1/p;" -e '}' ; }
S=$(cargo +nightly clippy --all-targets ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -- -D warnings 2>&1) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*$/::warning file=\2,line=\3,col=\4::WARNING: \`cargo clippy\`: \1/p;" -e '}' ; }
min_version:
name: MinRustV # Minimum supported rust version
@ -614,3 +614,20 @@ jobs:
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
name: codecov-umbrella
fail_ci_if_error: false
spellcheck:
name: Spell Check
runs-on: ${{ matrix.job.os }}
strategy:
matrix:
job:
- { os: ubuntu-latest }
steps:
- uses: actions/checkout@v1
- name: Install/setup prerequisites
shell: bash
run: |
sudo apt-get -y update ; sudo apt-get -y install npm ; sudo npm install cspell -g;
- name: Run `cspell`
shell: bash
run: |
cspell --config .vscode/cSpell.json --no-summary --no-progress $( git ls-files | grep "\.\(rs\|md\)" ) | sed "s/\(.*\):\(.*\):\(.*\) - \(.*\)/::warning file=\1,line=\2,col=\3::cspell: \4/" || true

View file

@ -1,8 +1,17 @@
# https://pre-commit.com
repos:
- repo: https://github.com/doublify/pre-commit-rust
rev: v1.0
- repo: local
hooks:
- id: cargo-check
- id: clippy
- id: fmt
- id: rust-linting
name: Rust linting
description: Run cargo fmt on files included in the commit.
entry: cargo +nightly fmt --
pass_filenames: true
types: [file, rust]
language: system
- id: rust-clippy
name: Rust clippy
description: Run cargo clippy on files included in the commit.
entry: cargo +nightly clippy --all-targets --all-features --
pass_filenames: false
types: [file, rust]
language: system

462
Cargo.lock generated
View file

@ -43,12 +43,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "array-init"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6945cc5422176fc5e602e590c2878d2c2acd9a4fe20a4baa7c28022521698ec6"
[[package]]
name = "arrayvec"
version = "0.4.12"
@ -134,15 +128,8 @@ dependencies = [
"lazy_static",
"memchr 2.4.0",
"regex-automata",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
[[package]]
name = "byte-tools"
version = "0.2.0"
@ -155,20 +142,11 @@ version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cast"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57cdfa5d50aad6cb4d44dcab6101a7f79925bd59d82ca42f38a9856a28865374"
dependencies = [
"rustc_version",
]
[[package]]
name = "cc"
version = "1.0.67"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
[[package]]
name = "cfg-if"
@ -244,6 +222,7 @@ dependencies = [
name = "coreutils"
version = "0.0.6"
dependencies = [
"atty",
"chrono",
"conv",
"filetime",
@ -285,7 +264,6 @@ dependencies = [
"uu_expand",
"uu_expr",
"uu_factor",
"uu_factor_benches",
"uu_false",
"uu_fmt",
"uu_fold",
@ -465,42 +443,6 @@ dependencies = [
"unicode-xid 0.0.4",
]
[[package]]
name = "criterion"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23"
dependencies = [
"atty",
"cast",
"clap",
"criterion-plot",
"csv",
"itertools 0.10.0",
"lazy_static",
"num-traits",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_cbor",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d"
dependencies = [
"cast",
"itertools 0.9.0",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
@ -524,9 +466,9 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
@ -537,35 +479,37 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
"lazy_static",
]
[[package]]
name = "csv"
version = "1.1.6"
name = "crossterm"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c"
dependencies = [
"bstr",
"csv-core",
"itoa",
"ryu",
"serde",
"bitflags",
"crossterm_winapi",
"lazy_static",
"libc",
"mio",
"parking_lot",
"signal-hook",
"winapi 0.3.9",
]
[[package]]
name = "csv-core"
version = "0.1.10"
name = "crossterm_winapi"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
checksum = "0da8964ace4d3e4a044fd027919b2237000b24315a37c916f61809f1ff2140b9"
dependencies = [
"memchr 2.4.0",
"winapi 0.3.9",
]
[[package]]
@ -794,6 +738,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46dbcb333e86939721589d25a3557e180b52778cb33c7fdfe9e0158ff790d5ec"
[[package]]
name = "instant"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "ioctl-sys"
version = "0.5.2"
@ -809,15 +762,6 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.10.0"
@ -827,21 +771,6 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "js-sys"
version = "0.3.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@ -873,6 +802,15 @@ dependencies = [
"libc",
]
[[package]]
name = "lock_api"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
@ -926,13 +864,35 @@ checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "memoffset"
version = "0.6.3"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [
"autocfg",
]
[[package]]
name = "mio"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e50ae3f04d169fcc9bde0b547d1c205219b7157e07ded9c5aff03e0637cb3ed7"
dependencies = [
"libc",
"log",
"miow",
"ntapi",
"winapi 0.3.9",
]
[[package]]
name = "miow"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "nix"
version = "0.13.1"
@ -964,6 +924,26 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "ntapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "num-bigint"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.44"
@ -1033,12 +1013,6 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "ouroboros"
version = "0.9.3"
@ -1071,6 +1045,31 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "parking_lot"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
dependencies = [
"cfg-if 1.0.0",
"instant",
"libc",
"redox_syscall 0.2.8",
"smallvec 1.6.1",
"winapi 0.3.9",
]
[[package]]
name = "paste"
version = "0.1.18"
@ -1090,15 +1089,6 @@ dependencies = [
"proc-macro-hack",
]
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]]
name = "pkg-config"
version = "0.3.19"
@ -1115,34 +1105,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "plotters"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b07fffcddc1cb3a1de753caa4e4df03b79922ba43cf882acc1bdd7e8df9f4590"
[[package]]
name = "plotters-svg"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b38a02e23bd9604b842a812063aec4ef702b57989c37b655254bb61c471ad211"
dependencies = [
"plotters-backend",
]
[[package]]
name = "ppv-lite86"
version = "0.2.10"
@ -1454,21 +1416,6 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
[[package]]
name = "rustc_version"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
dependencies = [
"semver 0.11.0",
]
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "same-file"
version = "1.0.6"
@ -1490,16 +1437,7 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser 0.7.0",
]
[[package]]
name = "semver"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
dependencies = [
"semver-parser 0.10.2",
"semver-parser",
]
[[package]]
@ -1508,53 +1446,6 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "semver-parser"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
dependencies = [
"pest",
]
[[package]]
name = "serde"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
[[package]]
name = "serde_cbor"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622"
dependencies = [
"half",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
dependencies = [
"proc-macro2",
"quote 1.0.9",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha1"
version = "0.6.0"
@ -1586,6 +1477,26 @@ dependencies = [
"generic-array",
]
[[package]]
name = "signal-hook"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729"
dependencies = [
"libc",
"mio",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-registry"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "0.6.14"
@ -1595,6 +1506,12 @@ dependencies = [
"maybe-uninit",
]
[[package]]
name = "smallvec"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "socket2"
version = "0.3.19"
@ -1717,18 +1634,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.24"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.24"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
dependencies = [
"proc-macro2",
"quote 1.0.9",
@ -1745,28 +1662,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "typenum"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
[[package]]
name = "ucd-trie"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unicode-segmentation"
version = "1.7.1"
@ -2053,6 +1954,8 @@ name = "uu_expr"
version = "0.0.6"
dependencies = [
"libc",
"num-bigint",
"num-traits",
"onig",
"uucore",
"uucore_procs",
@ -2068,22 +1971,11 @@ dependencies = [
"paste",
"quickcheck",
"rand 0.7.3",
"smallvec",
"smallvec 0.6.14",
"uucore",
"uucore_procs",
]
[[package]]
name = "uu_factor_benches"
version = "0.0.0"
dependencies = [
"array-init",
"criterion",
"rand 0.7.3",
"rand_chacha 0.2.2",
"uu_factor",
]
[[package]]
name = "uu_false"
version = "0.0.6"
@ -2306,7 +2198,9 @@ dependencies = [
name = "uu_more"
version = "0.0.6"
dependencies = [
"atty",
"clap",
"crossterm",
"nix 0.13.1",
"redox_syscall 0.1.57",
"redox_termios",
@ -2576,7 +2470,7 @@ dependencies = [
"ouroboros",
"rand 0.7.3",
"rayon",
"semver 0.9.0",
"semver",
"tempfile",
"unicode-width",
"uucore",
@ -2924,70 +2818,6 @@ version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasm-bindgen"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote 1.0.9",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4"
dependencies = [
"quote 1.0.9",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97"
dependencies = [
"proc-macro2",
"quote 1.0.9",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f"
[[package]]
name = "web-sys"
version = "0.3.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "wild"
version = "2.0.4"

View file

@ -327,7 +327,8 @@ who = { optional=true, version="0.0.6", package="uu_who", path="src/uu/who"
whoami = { optional=true, version="0.0.6", package="uu_whoami", path="src/uu/whoami" }
yes = { optional=true, version="0.0.6", package="uu_yes", path="src/uu/yes" }
factor_benches = { optional = true, version = "0.0.0", package = "uu_factor_benches", path = "tests/benches/factor" }
# this breaks clippy linting with: "tests/by-util/test_factor_benches.rs: No such file or directory (os error 2)"
# factor_benches = { optional = true, version = "0.0.0", package = "uu_factor_benches", path = "tests/benches/factor" }
#
# * pinned transitive dependencies
@ -350,6 +351,7 @@ time = "0.1"
unindent = "0.1"
uucore = { version=">=0.0.8", package="uucore", path="src/uucore", features=["entries"] }
walkdir = "2.2"
atty = "0.2.14"
[target.'cfg(unix)'.dev-dependencies]
rust-users = { version="0.10", package="users" }

View file

@ -21,7 +21,7 @@ if changes are not reflected in the report then run `cargo clean` and run the a
### Using Stable Rust
If you are using stable version of Rust that doesn't enable code coverage instrumentation by default
If you are using stable version of Rust that doesn't enable code coverage instrumentation by default
then add `-Z-Zinstrument-coverage` flag to `RUSTFLAGS` env variable specified above.
@ -36,3 +36,7 @@ To use the provided hook:
2. Run `pre-commit install` while in the repository directory
Your git commits will then automatically be checked. If a check fails, an error message will explain why, and your commit will be canceled. You can then make the suggested changes, and run `git commit ...` again.
### Using Clippy
The `msrv` key in the clippy configuration file `clippy.toml` is used to disable lints pertaining to newer features by specifying the minimum supported Rust version (MSRV). However, this key is only supported on `nightly`. To invoke clippy without errors, use `cargo +nightly clippy`. In order to also check tests and non-default crate features, use `cargo +nightly clippy --all-targets --all-features`.

1
clippy.toml Normal file
View file

@ -0,0 +1 @@
msrv = "1.43.1"

View file

@ -136,7 +136,8 @@ fn basename(fullname: &str, suffix: &str) -> String {
}
}
#[allow(clippy::manual_strip)] // can be replaced with strip_suffix once the minimum rust version is 1.45
// can be replaced with strip_suffix once MSRV is 1.45
#[allow(clippy::manual_strip)]
fn strip_suffix(name: &str, suffix: &str) -> String {
if name == suffix {
return name.to_owned();

View file

@ -669,8 +669,8 @@ impl Options {
}
},
backup: backup_mode,
backup_suffix: backup_suffix,
overwrite: overwrite,
backup_suffix,
overwrite,
no_target_dir,
preserve_attributes,
recursive,
@ -1089,7 +1089,7 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu
}
#[cfg(not(windows))]
#[allow(clippy::unnecessary_wraps)] // needed for windows version
#[allow(clippy::unnecessary_unwrap)] // needed for windows version
fn symlink_file(source: &Path, dest: &Path, context: &str) -> CopyResult<()> {
match std::os::unix::fs::symlink(source, dest).context(context) {
Ok(_) => Ok(()),
@ -1108,7 +1108,7 @@ fn context_for(src: &Path, dest: &Path) -> String {
/// Implements a simple backup copy for the destination file.
/// TODO: for the backup, should this function be replaced by `copy_file(...)`?
fn backup_dest(dest: &Path, backup_path: &PathBuf) -> CopyResult<PathBuf> {
fn backup_dest(dest: &Path, backup_path: &Path) -> CopyResult<PathBuf> {
fs::copy(dest, &backup_path)?;
Ok(backup_path.into())
}

View file

@ -483,10 +483,11 @@ where
/// Shrink the buffer so that its length is equal to the set size, returning an iterator for
/// the elements that were too much.
fn shrink_buffer_to_size(&mut self) -> impl Iterator<Item = String> + '_ {
let mut shrink_offset = 0;
if self.buffer.len() > self.size {
shrink_offset = self.buffer.len() - self.size;
}
let shrink_offset = if self.buffer.len() > self.size {
self.buffer.len() - self.size
} else {
0
};
self.buffer
.drain(..shrink_offset)
.map(|(_, line)| line.unwrap())

View file

@ -16,6 +16,8 @@ path = "src/expr.rs"
[dependencies]
libc = "0.2.42"
num-bigint = "0.4.0"
num-traits = "0.2.14"
onig = "~4.3.2"
uucore = { version=">=0.0.8", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -12,6 +12,8 @@
// spell-checker:ignore (ToDO) binop binops ints paren prec
use num_bigint::BigInt;
use num_traits::{One, Zero};
use onig::{Regex, RegexOptions, Syntax};
use crate::tokens::Token;
@ -39,20 +41,17 @@ impl AstNode {
for _ in 0..depth {
print!("\t",);
}
match *self {
AstNode::Leaf {
ref token_idx,
ref value,
} => println!(
match self {
AstNode::Leaf { token_idx, value } => println!(
"Leaf( {} ) at #{} ( evaluate -> {:?} )",
value,
token_idx,
self.evaluate()
),
AstNode::Node {
ref token_idx,
ref op_type,
ref operands,
token_idx,
op_type,
operands,
} => {
println!(
"Node( {} ) at #{} (evaluate -> {:?})",
@ -81,36 +80,33 @@ impl AstNode {
})
}
pub fn evaluate(&self) -> Result<String, String> {
match *self {
AstNode::Leaf { ref value, .. } => Ok(value.clone()),
AstNode::Node { ref op_type, .. } => match self.operand_values() {
match self {
AstNode::Leaf { value, .. } => Ok(value.clone()),
AstNode::Node { op_type, .. } => match self.operand_values() {
Err(reason) => Err(reason),
Ok(operand_values) => match op_type.as_ref() {
"+" => infix_operator_two_ints(
|a: i64, b: i64| checked_binop(|| a.checked_add(b), "+"),
&operand_values,
),
"-" => infix_operator_two_ints(
|a: i64, b: i64| checked_binop(|| a.checked_sub(b), "-"),
&operand_values,
),
"*" => infix_operator_two_ints(
|a: i64, b: i64| checked_binop(|| a.checked_mul(b), "*"),
&operand_values,
),
"+" => {
infix_operator_two_ints(|a: BigInt, b: BigInt| Ok(a + b), &operand_values)
}
"-" => {
infix_operator_two_ints(|a: BigInt, b: BigInt| Ok(a - b), &operand_values)
}
"*" => {
infix_operator_two_ints(|a: BigInt, b: BigInt| Ok(a * b), &operand_values)
}
"/" => infix_operator_two_ints(
|a: i64, b: i64| {
if b == 0 {
|a: BigInt, b: BigInt| {
if b.is_zero() {
Err("division by zero".to_owned())
} else {
checked_binop(|| a.checked_div(b), "/")
Ok(a / b)
}
},
&operand_values,
),
"%" => infix_operator_two_ints(
|a: i64, b: i64| {
if b == 0 {
|a: BigInt, b: BigInt| {
if b.is_zero() {
Err("division by zero".to_owned())
} else {
Ok(a % b)
@ -119,32 +115,32 @@ impl AstNode {
&operand_values,
),
"=" => infix_operator_two_ints_or_two_strings(
|a: i64, b: i64| Ok(bool_as_int(a == b)),
|a: BigInt, b: BigInt| Ok(bool_as_int(a == b)),
|a: &String, b: &String| Ok(bool_as_string(a == b)),
&operand_values,
),
"!=" => infix_operator_two_ints_or_two_strings(
|a: i64, b: i64| Ok(bool_as_int(a != b)),
|a: BigInt, b: BigInt| Ok(bool_as_int(a != b)),
|a: &String, b: &String| Ok(bool_as_string(a != b)),
&operand_values,
),
"<" => infix_operator_two_ints_or_two_strings(
|a: i64, b: i64| Ok(bool_as_int(a < b)),
|a: BigInt, b: BigInt| Ok(bool_as_int(a < b)),
|a: &String, b: &String| Ok(bool_as_string(a < b)),
&operand_values,
),
">" => infix_operator_two_ints_or_two_strings(
|a: i64, b: i64| Ok(bool_as_int(a > b)),
|a: BigInt, b: BigInt| Ok(bool_as_int(a > b)),
|a: &String, b: &String| Ok(bool_as_string(a > b)),
&operand_values,
),
"<=" => infix_operator_two_ints_or_two_strings(
|a: i64, b: i64| Ok(bool_as_int(a <= b)),
|a: BigInt, b: BigInt| Ok(bool_as_int(a <= b)),
|a: &String, b: &String| Ok(bool_as_string(a <= b)),
&operand_values,
),
">=" => infix_operator_two_ints_or_two_strings(
|a: i64, b: i64| Ok(bool_as_int(a >= b)),
|a: BigInt, b: BigInt| Ok(bool_as_int(a >= b)),
|a: &String, b: &String| Ok(bool_as_string(a >= b)),
&operand_values,
),
@ -161,7 +157,7 @@ impl AstNode {
}
}
pub fn operand_values(&self) -> Result<Vec<String>, String> {
if let AstNode::Node { ref operands, .. } = *self {
if let AstNode::Node { operands, .. } = self {
let mut out = Vec::with_capacity(operands.len());
for operand in operands {
match operand.evaluate() {
@ -217,9 +213,9 @@ fn maybe_dump_ast(result: &Result<Box<AstNode>, String>) {
if let Ok(debug_var) = env::var("EXPR_DEBUG_AST") {
if debug_var == "1" {
println!("EXPR_DEBUG_AST");
match *result {
Ok(ref ast) => ast.debug_dump(),
Err(ref reason) => println!("\terr: {:?}", reason),
match result {
Ok(ast) => ast.debug_dump(),
Err(reason) => println!("\terr: {:?}", reason),
}
}
}
@ -304,7 +300,7 @@ fn push_token_to_either_stack(
out_stack: &mut TokenStack,
op_stack: &mut TokenStack,
) -> Result<(), String> {
let result = match *token {
let result = match token {
Token::Value { .. } => {
out_stack.push((token_idx, token.clone()));
Ok(())
@ -420,24 +416,14 @@ fn move_till_match_paren(
}
}
fn checked_binop<F: Fn() -> Option<T>, T>(cb: F, op: &str) -> Result<T, String> {
match cb() {
Some(v) => Ok(v),
None => Err(format!("{}: Numerical result out of range", op)),
}
}
fn infix_operator_two_ints<F>(f: F, values: &[String]) -> Result<String, String>
where
F: Fn(i64, i64) -> Result<i64, String>,
F: Fn(BigInt, BigInt) -> Result<BigInt, String>,
{
assert!(values.len() == 2);
if let Ok(left) = values[0].parse::<i64>() {
if let Ok(right) = values[1].parse::<i64>() {
return match f(left, right) {
Ok(result) => Ok(result.to_string()),
Err(reason) => Err(reason),
};
if let Ok(left) = values[0].parse::<BigInt>() {
if let Ok(right) = values[1].parse::<BigInt>() {
return f(left, right).map(|big_int| big_int.to_string());
}
}
Err("Expected an integer operand".to_string())
@ -449,13 +435,14 @@ fn infix_operator_two_ints_or_two_strings<FI, FS>(
values: &[String],
) -> Result<String, String>
where
FI: Fn(i64, i64) -> Result<i64, String>,
FI: Fn(BigInt, BigInt) -> Result<u8, String>,
FS: Fn(&String, &String) -> Result<String, String>,
{
assert!(values.len() == 2);
if let (Some(a_int), Some(b_int)) =
(values[0].parse::<i64>().ok(), values[1].parse::<i64>().ok())
{
if let (Some(a_int), Some(b_int)) = (
values[0].parse::<BigInt>().ok(),
values[1].parse::<BigInt>().ok(),
) {
match fi(a_int, b_int) {
Ok(result) => Ok(result.to_string()),
Err(reason) => Err(reason),
@ -541,7 +528,7 @@ fn prefix_operator_substr(values: &[String]) -> String {
subj.chars().skip(idx).take(len).collect()
}
fn bool_as_int(b: bool) -> i64 {
fn bool_as_int(b: bool) -> u8 {
if b {
1
} else {
@ -559,8 +546,8 @@ fn value_as_bool(s: &str) -> bool {
if s.is_empty() {
return false;
}
match s.parse::<i64>() {
Ok(n) => n != 0,
match s.parse::<BigInt>() {
Ok(n) => n.is_one(),
Err(_) => true,
}
}

View file

@ -18,6 +18,8 @@
// spell-checker:ignore (ToDO) paren
use num_bigint::BigInt;
#[derive(Debug, Clone)]
pub enum Token {
Value {
@ -51,14 +53,14 @@ impl Token {
}
fn is_infix_plus(&self) -> bool {
match *self {
Token::InfixOp { ref value, .. } => value == "+",
match self {
Token::InfixOp { value, .. } => value == "+",
_ => false,
}
}
fn is_a_number(&self) -> bool {
match *self {
Token::Value { ref value, .. } => value.parse::<i64>().is_ok(),
match self {
Token::Value { value, .. } => value.parse::<BigInt>().is_ok(),
_ => false,
}
}
@ -142,7 +144,7 @@ fn push_token_if_not_escaped(acc: &mut Vec<(usize, Token)>, tok_idx: usize, toke
// Smells heuristics... :(
let prev_is_plus = match acc.last() {
None => false,
Some(ref t) => t.1.is_infix_plus(),
Some(t) => t.1.is_infix_plus(),
};
let should_use_as_escaped = if prev_is_plus && acc.len() >= 2 {
let pre_prev = &acc[acc.len() - 2];

View file

@ -30,7 +30,7 @@ impl Iterator for Sieve {
#[inline]
fn next(&mut self) -> Option<u64> {
while let Some(n) = self.inner.next() {
for n in &mut self.inner {
let mut prime = true;
while let Some((next, inc)) = self.filts.peek() {
// need to keep checking the min element of the heap

View file

@ -14,7 +14,7 @@ pub fn parse_obsolete(src: &str) -> Option<Result<impl Iterator<Item = OsString>
let mut num_end = 0usize;
let mut has_num = false;
let mut last_char = 0 as char;
while let Some((n, c)) = chars.next() {
for (n, c) in &mut chars {
if c.is_numeric() {
has_num = true;
num_end = n;
@ -109,7 +109,7 @@ pub fn parse_num(src: &str) -> Result<(usize, bool), ParseError> {
let mut num_end = 0usize;
let mut last_char = 0 as char;
let mut num_count = 0usize;
while let Some((n, c)) = chars.next() {
for (n, c) in &mut chars {
if c.is_numeric() {
num_end = n;
num_count += 1;

View file

@ -520,6 +520,7 @@ fn copy_file_to_file(file: &Path, target: &Path, b: &Behavior) -> i32 {
///
/// If the copy system call fails, we print a verbose error and return an empty error value.
///
#[allow(clippy::cognitive_complexity)]
fn copy(from: &Path, to: &Path, b: &Behavior) -> Result<(), ()> {
if b.compare && !need_copy(from, to, b) {
return Ok(());

View file

@ -218,6 +218,7 @@ struct LongFormat {
}
impl Config {
#[allow(clippy::cognitive_complexity)]
fn from(options: clap::ArgMatches) -> Config {
let (mut format, opt) = if let Some(format_) = options.value_of(options::FORMAT) {
(
@ -1222,7 +1223,7 @@ fn list(locs: Vec<String>, config: Config) -> i32 {
sort_entries(&mut dirs, &config);
for dir in dirs {
if locs.len() > 1 {
if locs.len() > 1 || config.recursive {
let _ = writeln!(out, "\n{}:", dir.p_buf.display());
}
enter_directory(&dir, &config, &mut out);
@ -1614,7 +1615,7 @@ fn display_date(metadata: &Metadata, config: &Config) -> String {
Some(time) => {
//Date is recent if from past 6 months
//According to GNU a Gregorian year has 365.2425 * 24 * 60 * 60 == 31556952 seconds on the average.
let recent = time + chrono::Duration::seconds(31556952 / 2) > chrono::Local::now();
let recent = time + chrono::Duration::seconds(31_556_952 / 2) > chrono::Local::now();
match config.time_style {
TimeStyle::FullIso => time.format("%Y-%m-%d %H:%M:%S.%f %z"),
@ -1696,7 +1697,6 @@ fn file_is_executable(md: &Metadata) -> bool {
md.mode() & ((S_IXUSR | S_IXGRP | S_IXOTH) as u32) != 0
}
#[allow(clippy::clippy::collapsible_else_if)]
fn classify_file(path: &PathData) -> Option<char> {
let file_type = path.file_type()?;

View file

@ -18,6 +18,8 @@ path = "src/more.rs"
clap = "2.33"
uucore = { version = ">=0.0.7", package = "uucore", path = "../../uucore" }
uucore_procs = { version = ">=0.0.5", package = "uucore_procs", path = "../../uucore_procs" }
crossterm = ">=0.19"
atty = "0.2.14"
[target.'cfg(target_os = "redox")'.dependencies]
redox_termios = "0.1"

View file

@ -10,150 +10,395 @@
#[macro_use]
extern crate uucore;
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, Read, Write};
use std::{
convert::TryInto,
fs::File,
io::{stdin, stdout, BufReader, Read, Stdout, Write},
path::Path,
time::Duration,
};
#[cfg(all(unix, not(target_os = "fuchsia")))]
extern crate nix;
#[cfg(all(unix, not(target_os = "fuchsia")))]
use nix::sys::termios::{self, LocalFlags, SetArg};
use uucore::InvalidEncodingHandling;
#[cfg(target_os = "redox")]
extern crate redox_termios;
#[cfg(target_os = "redox")]
extern crate syscall;
use clap::{App, Arg};
use crossterm::{
event::{self, Event, KeyCode, KeyEvent, KeyModifiers},
execute, queue,
style::Attribute,
terminal,
};
use clap::{App, Arg, ArgMatches};
static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "A file perusal filter for CRT viewing.";
mod options {
pub const FILE: &str = "file";
pub mod options {
pub const SILENT: &str = "silent";
pub const LOGICAL: &str = "logical";
pub const NO_PAUSE: &str = "no-pause";
pub const PRINT_OVER: &str = "print-over";
pub const CLEAN_PRINT: &str = "clean-print";
pub const SQUEEZE: &str = "squeeze";
pub const PLAIN: &str = "plain";
pub const LINES: &str = "lines";
pub const NUMBER: &str = "number";
pub const PATTERN: &str = "pattern";
pub const FROM_LINE: &str = "from-line";
pub const FILES: &str = "files";
}
fn get_usage() -> String {
format!("{} [options] <file>...", executable!())
}
const MULTI_FILE_TOP_PROMPT: &str = "::::::::::::::\n{}\n::::::::::::::\n";
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let args = args
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
.version(VERSION)
.usage(usage.as_str())
.about(ABOUT)
.about("A file perusal filter for CRT viewing.")
.version(env!("CARGO_PKG_VERSION"))
// The commented arguments below are unimplemented:
/*
.arg(
Arg::with_name(options::FILE)
.number_of_values(1)
.multiple(true),
Arg::with_name(options::SILENT)
.short("d")
.long(options::SILENT)
.help("Display help instead of ringing bell"),
)
.arg(
Arg::with_name(options::LOGICAL)
.short("f")
.long(options::LOGICAL)
.help("Count logical rather than screen lines"),
)
.arg(
Arg::with_name(options::NO_PAUSE)
.short("l")
.long(options::NO_PAUSE)
.help("Suppress pause after form feed"),
)
.arg(
Arg::with_name(options::PRINT_OVER)
.short("c")
.long(options::PRINT_OVER)
.help("Do not scroll, display text and clean line ends"),
)
.arg(
Arg::with_name(options::CLEAN_PRINT)
.short("p")
.long(options::CLEAN_PRINT)
.help("Do not scroll, clean screen and display text"),
)
.arg(
Arg::with_name(options::SQUEEZE)
.short("s")
.long(options::SQUEEZE)
.help("Squeeze multiple blank lines into one"),
)
.arg(
Arg::with_name(options::PLAIN)
.short("u")
.long(options::PLAIN)
.help("Suppress underlining and bold"),
)
.arg(
Arg::with_name(options::LINES)
.short("n")
.long(options::LINES)
.value_name("number")
.takes_value(true)
.help("The number of lines per screenful"),
)
.arg(
Arg::with_name(options::NUMBER)
.allow_hyphen_values(true)
.long(options::NUMBER)
.required(false)
.takes_value(true)
.help("Same as --lines"),
)
.arg(
Arg::with_name(options::FROM_LINE)
.short("F")
.allow_hyphen_values(true)
.required(false)
.takes_value(true)
.value_name("number")
.help("Display file beginning from line number"),
)
.arg(
Arg::with_name(options::PATTERN)
.short("P")
.allow_hyphen_values(true)
.required(false)
.takes_value(true)
.help("Display file beginning from pattern match"),
)
*/
.arg(
Arg::with_name(options::FILES)
.required(false)
.multiple(true)
.help("Path to the files to be read"),
)
.get_matches_from(args);
// FixME: fail without panic for now; but `more` should work with no arguments (ie, for piped input)
if let None | Some("-") = matches.value_of(options::FILE) {
show_usage_error!("Reading from stdin isn't supported yet.");
return 1;
}
if let Some(x) = matches.value_of(options::FILE) {
let path = std::path::Path::new(x);
if path.is_dir() {
show_usage_error!("'{}' is a directory.", x);
return 1;
let mut buff = String::new();
if let Some(filenames) = matches.values_of(options::FILES) {
let mut stdout = setup_term();
let length = filenames.len();
for (idx, fname) in filenames.enumerate() {
let fname = Path::new(fname);
if fname.is_dir() {
terminal::disable_raw_mode().unwrap();
show_usage_error!("'{}' is a directory.", fname.display());
return 1;
}
if !fname.exists() {
terminal::disable_raw_mode().unwrap();
show_error!(
"cannot open {}: No such file or directory",
fname.display()
);
return 1;
}
if length > 1 {
buff.push_str(&MULTI_FILE_TOP_PROMPT.replace("{}", fname.to_str().unwrap()));
}
let mut reader = BufReader::new(File::open(fname).unwrap());
reader.read_to_string(&mut buff).unwrap();
let is_last = idx + 1 == length;
more(&buff, &mut stdout, is_last);
buff.clear();
}
reset_term(&mut stdout);
} else if atty::isnt(atty::Stream::Stdin) {
stdin().read_to_string(&mut buff).unwrap();
let mut stdout = setup_term();
more(&buff, &mut stdout, true);
reset_term(&mut stdout);
} else {
show_usage_error!("bad usage");
}
more(matches);
0
}
#[cfg(all(unix, not(target_os = "fuchsia")))]
fn setup_term() -> termios::Termios {
let mut term = termios::tcgetattr(0).unwrap();
// Unset canonical mode, so we get characters immediately
term.local_flags.remove(LocalFlags::ICANON);
// Disable local echo
term.local_flags.remove(LocalFlags::ECHO);
termios::tcsetattr(0, SetArg::TCSADRAIN, &term).unwrap();
term
#[cfg(not(target_os = "fuchsia"))]
fn setup_term() -> std::io::Stdout {
let stdout = stdout();
terminal::enable_raw_mode().unwrap();
stdout
}
#[cfg(any(windows, target_os = "fuchsia"))]
#[cfg(target_os = "fuchsia")]
#[inline(always)]
fn setup_term() -> usize {
0
}
#[cfg(target_os = "redox")]
fn setup_term() -> redox_termios::Termios {
let mut term = redox_termios::Termios::default();
let fd = syscall::dup(0, b"termios").unwrap();
syscall::read(fd, &mut term).unwrap();
term.local_flags &= !redox_termios::ICANON;
term.local_flags &= !redox_termios::ECHO;
syscall::write(fd, &term).unwrap();
let _ = syscall::close(fd);
term
#[cfg(not(target_os = "fuchsia"))]
fn reset_term(stdout: &mut std::io::Stdout) {
terminal::disable_raw_mode().unwrap();
// Clear the prompt
queue!(stdout, terminal::Clear(terminal::ClearType::CurrentLine)).unwrap();
// Move cursor to the beginning without printing new line
print!("\r");
stdout.flush().unwrap();
}
#[cfg(all(unix, not(target_os = "fuchsia")))]
fn reset_term(term: &mut termios::Termios) {
term.local_flags.insert(LocalFlags::ICANON);
term.local_flags.insert(LocalFlags::ECHO);
termios::tcsetattr(0, SetArg::TCSADRAIN, &term).unwrap();
}
#[cfg(any(windows, target_os = "fuchsia"))]
#[cfg(target_os = "fuchsia")]
#[inline(always)]
fn reset_term(_: &mut usize) {}
#[cfg(any(target_os = "redox"))]
fn reset_term(term: &mut redox_termios::Termios) {
let fd = syscall::dup(0, b"termios").unwrap();
syscall::read(fd, term).unwrap();
term.local_flags |= redox_termios::ICANON;
term.local_flags |= redox_termios::ECHO;
syscall::write(fd, &term).unwrap();
let _ = syscall::close(fd);
}
fn more(buff: &str, mut stdout: &mut Stdout, is_last: bool) {
let (cols, rows) = terminal::size().unwrap();
let lines = break_buff(buff, usize::from(cols));
let line_count: u16 = lines.len().try_into().unwrap();
fn more(matches: ArgMatches) {
let mut f: Box<dyn BufRead> = match matches.value_of(options::FILE) {
None | Some("-") => Box::new(BufReader::new(stdin())),
Some(filename) => Box::new(BufReader::new(File::open(filename).unwrap())),
};
let mut buffer = [0; 1024];
let mut upper_mark = 0;
let mut lines_left = line_count.saturating_sub(upper_mark + rows);
let mut term = setup_term();
draw(
&mut upper_mark,
rows,
&mut stdout,
lines.clone(),
line_count,
);
let mut end = false;
while let Ok(sz) = f.read(&mut buffer) {
if sz == 0 {
break;
}
stdout().write_all(&buffer[0..sz]).unwrap();
for byte in std::io::stdin().bytes() {
match byte.unwrap() {
b' ' => break,
b'q' | 27 => {
end = true;
break;
}
_ => (),
}
}
if end {
break;
// Specifies whether we have reached the end of the file and should
// return on the next keypress. However, we immediately return when
// this is the last file.
let mut to_be_done = false;
if lines_left == 0 && is_last {
if is_last {
return;
} else {
to_be_done = true;
}
}
loop {
if event::poll(Duration::from_millis(10)).unwrap() {
match event::read().unwrap() {
Event::Key(KeyEvent {
code: KeyCode::Char('q'),
modifiers: KeyModifiers::NONE,
})
| Event::Key(KeyEvent {
code: KeyCode::Char('c'),
modifiers: KeyModifiers::CONTROL,
}) => {
reset_term(&mut stdout);
std::process::exit(0);
}
Event::Key(KeyEvent {
code: KeyCode::Down,
modifiers: KeyModifiers::NONE,
})
| Event::Key(KeyEvent {
code: KeyCode::Char(' '),
modifiers: KeyModifiers::NONE,
}) => {
upper_mark = upper_mark.saturating_add(rows.saturating_sub(1));
}
Event::Key(KeyEvent {
code: KeyCode::Up,
modifiers: KeyModifiers::NONE,
}) => {
upper_mark = upper_mark.saturating_sub(rows.saturating_sub(1));
}
_ => continue,
}
lines_left = line_count.saturating_sub(upper_mark + rows);
draw(
&mut upper_mark,
rows,
&mut stdout,
lines.clone(),
line_count,
);
reset_term(&mut term);
println!();
if lines_left == 0 {
if to_be_done || is_last {
return
}
to_be_done = true;
}
}
}
}
fn draw(
upper_mark: &mut u16,
rows: u16,
mut stdout: &mut std::io::Stdout,
lines: Vec<String>,
lc: u16,
) {
execute!(stdout, terminal::Clear(terminal::ClearType::CurrentLine)).unwrap();
let (up_mark, lower_mark) = calc_range(*upper_mark, rows, lc);
// Reduce the row by 1 for the prompt
let displayed_lines = lines
.iter()
.skip(up_mark.into())
.take(usize::from(rows.saturating_sub(1)));
for line in displayed_lines {
stdout
.write_all(format!("\r{}\n", line).as_bytes())
.unwrap();
}
make_prompt_and_flush(&mut stdout, lower_mark, lc);
*upper_mark = up_mark;
}
// Break the lines on the cols of the terminal
fn break_buff(buff: &str, cols: usize) -> Vec<String> {
let mut lines = Vec::new();
for l in buff.lines() {
lines.append(&mut break_line(l, cols));
}
lines
}
fn break_line(mut line: &str, cols: usize) -> Vec<String> {
let breaks = (line.len() / cols).saturating_add(1);
let mut lines = Vec::with_capacity(breaks);
// TODO: Use unicode width instead of the length in bytes.
if line.len() < cols {
lines.push(line.to_string());
return lines;
}
for _ in 1..=breaks {
let (line1, line2) = line.split_at(cols);
lines.push(line1.to_string());
if line2.len() < cols {
lines.push(line2.to_string());
break;
}
line = line2;
}
lines
}
// Calculate upper_mark based on certain parameters
fn calc_range(mut upper_mark: u16, rows: u16, line_count: u16) -> (u16, u16) {
let mut lower_mark = upper_mark.saturating_add(rows);
if lower_mark >= line_count {
upper_mark = line_count.saturating_sub(rows);
lower_mark = line_count;
} else {
lower_mark = lower_mark.saturating_sub(1)
}
(upper_mark, lower_mark)
}
// Make a prompt similar to original more
fn make_prompt_and_flush(stdout: &mut Stdout, lower_mark: u16, lc: u16) {
write!(
stdout,
"\r{}--More--({}%){}",
Attribute::Reverse,
((lower_mark as f64 / lc as f64) * 100.0).round() as u16,
Attribute::Reset
)
.unwrap();
stdout.flush().unwrap();
}
#[cfg(test)]
mod tests {
use super::{break_line, calc_range};
// It is good to test the above functions
#[test]
fn test_calc_range() {
assert_eq!((0, 24), calc_range(0, 25, 100));
assert_eq!((50, 74), calc_range(50, 25, 100));
assert_eq!((75, 100), calc_range(85, 25, 100));
}
#[test]
fn test_break_lines_long() {
let mut test_string = String::with_capacity(100);
for _ in 0..200 {
test_string.push('#');
}
let lines = break_line(&test_string, 80);
assert_eq!(
(80, 80, 40),
(lines[0].len(), lines[1].len(), lines[2].len())
);
}
#[test]
fn test_break_lines_short() {
let mut test_string = String::with_capacity(100);
for _ in 0..20 {
test_string.push('#');
}
let lines = break_line(&test_string, 80);
assert_eq!(20, lines[0].len());
}
}

View file

@ -76,7 +76,7 @@ pub fn parse_inputs(matches: &dyn CommandLineOpts) -> Result<CommandLineInputs,
input_strings.push("-");
}
Ok(CommandLineInputs::FileNames(
input_strings.iter().map(|s| s.to_string()).collect(),
input_strings.iter().map(|&s| s.to_string()).collect(),
))
}
@ -92,7 +92,7 @@ pub fn parse_inputs_traditional(input_strings: Vec<&str>) -> Result<CommandLineI
Ok(match offset0 {
Ok(n) => CommandLineInputs::FileAndOffset(("-".to_string(), n, None)),
_ => CommandLineInputs::FileNames(
input_strings.iter().map(|s| s.to_string()).collect(),
input_strings.iter().map(|&s| s.to_string()).collect(),
),
})
}
@ -179,7 +179,7 @@ mod tests {
impl<'a> MockOptions<'a> {
fn new(inputs: Vec<&'a str>, option_names: Vec<&'a str>) -> MockOptions<'a> {
MockOptions {
inputs: inputs.iter().map(|s| s.to_string()).collect::<Vec<_>>(),
inputs: inputs.iter().map(|&s| s.to_string()).collect::<Vec<_>>(),
option_names,
}
}

View file

@ -50,10 +50,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let mut separator = "\n";
if matches.is_present(OPT_NULL) {
separator = "\x00";
}
let separator = if matches.is_present(OPT_NULL) {
"\x00"
} else {
"\n"
};
if variables.is_empty() {
for (env_var, value) in env::vars() {

View file

@ -108,10 +108,13 @@ impl WordFilter {
// Ignore empty string regex from cmd-line-args
let arg_reg: Option<String> = if matches.is_present(options::WORD_REGEXP) {
match matches.value_of(options::WORD_REGEXP) {
Some(v) => match v.is_empty() {
true => None,
false => Some(v.to_string()),
},
Some(v) => {
if v.is_empty() {
None
} else {
Some(v.to_string())
}
}
None => None,
}
} else {

View file

@ -2,7 +2,7 @@
Most of the time when sorting is spent comparing lines. The comparison functions however differ based
on which arguments are passed to `sort`, therefore it is important to always benchmark multiple scenarios.
This is an overwiew over what was benchmarked, and if you make changes to `sort`, you are encouraged to check
This is an overview over what was benchmarked, and if you make changes to `sort`, you are encouraged to check
how performance was affected for the workloads listed below. Feel free to add other workloads to the
list that we should improve / make sure not to regress.

View file

@ -73,6 +73,7 @@ impl Chunk {
/// * `lines`: The recycled vector to fill with lines. Must be empty.
/// * `settings`: The global settings.
#[allow(clippy::too_many_arguments)]
#[allow(clippy::borrowed_box)]
pub fn read(
sender_option: &mut Option<SyncSender<Chunk>>,
mut buffer: Vec<u8>,
@ -164,6 +165,7 @@ fn parse_lines<'a>(
/// The remaining bytes must be copied to the start of the buffer for the next invocation,
/// if another invocation is necessary, which is determined by the other return value.
/// * Whether this function should be called again.
#[allow(clippy::borrowed_box)]
fn read_to_buffer(
file: &mut Box<dyn Read + Send>,
next_files: &mut impl Iterator<Item = Box<dyn Read + Send>>,

View file

@ -108,7 +108,7 @@ const POSITIVE: char = '+';
// available memory into consideration, instead of relying on this constant only.
static DEFAULT_BUF_SIZE: usize = 1_000_000_000; // 1 GB
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Copy)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Copy, Debug)]
enum SortMode {
Numeric,
HumanNumeric,
@ -118,6 +118,21 @@ enum SortMode {
Random,
Default,
}
impl SortMode {
fn get_short_name(&self) -> Option<char> {
match self {
SortMode::Numeric => Some('n'),
SortMode::HumanNumeric => Some('h'),
SortMode::GeneralNumeric => Some('g'),
SortMode::Month => Some('M'),
SortMode::Version => Some('V'),
SortMode::Random => Some('R'),
SortMode::Default => None,
}
}
}
#[derive(Clone)]
pub struct GlobalSettings {
mode: SortMode,
@ -211,7 +226,7 @@ impl Default for GlobalSettings {
}
}
}
#[derive(Clone)]
#[derive(Clone, PartialEq, Debug)]
struct KeySettings {
mode: SortMode,
ignore_blanks: bool,
@ -221,6 +236,60 @@ struct KeySettings {
reverse: bool,
}
impl KeySettings {
/// Checks if the supplied combination of `mode`, `ignore_non_printing` and `dictionary_order` is allowed.
fn check_compatibility(
mode: SortMode,
ignore_non_printing: bool,
dictionary_order: bool,
) -> Result<(), String> {
if matches!(
mode,
SortMode::Numeric | SortMode::HumanNumeric | SortMode::GeneralNumeric | SortMode::Month
) {
if dictionary_order {
return Err(format!(
"options '-{}{}' are incompatible",
'd',
mode.get_short_name().unwrap()
));
} else if ignore_non_printing {
return Err(format!(
"options '-{}{}' are incompatible",
'i',
mode.get_short_name().unwrap()
));
}
}
Ok(())
}
fn set_sort_mode(&mut self, mode: SortMode) -> Result<(), String> {
if self.mode != SortMode::Default {
return Err(format!(
"options '-{}{}' are incompatible",
self.mode.get_short_name().unwrap(),
mode.get_short_name().unwrap()
));
}
Self::check_compatibility(mode, self.ignore_non_printing, self.dictionary_order)?;
self.mode = mode;
Ok(())
}
fn set_dictionary_order(&mut self) -> Result<(), String> {
Self::check_compatibility(self.mode, self.ignore_non_printing, true)?;
self.dictionary_order = true;
Ok(())
}
fn set_ignore_non_printing(&mut self) -> Result<(), String> {
Self::check_compatibility(self.mode, true, self.dictionary_order)?;
self.ignore_non_printing = true;
Ok(())
}
}
impl From<&GlobalSettings> for KeySettings {
fn from(settings: &GlobalSettings) -> Self {
Self {
@ -234,6 +303,12 @@ impl From<&GlobalSettings> for KeySettings {
}
}
impl Default for KeySettings {
fn default() -> Self {
Self::from(&GlobalSettings::default())
}
}
#[derive(Clone, Debug)]
enum NumCache {
AsF64(GeneralF64ParseResult),
@ -296,10 +371,10 @@ impl<'a> Line<'a> {
fn print(&self, writer: &mut impl Write, settings: &GlobalSettings) {
if settings.zero_terminated && !settings.debug {
crash_if_err!(1, writer.write_all(self.line.as_bytes()));
crash_if_err!(1, writer.write_all("\0".as_bytes()));
crash_if_err!(1, writer.write_all(b"\0"));
} else if !settings.debug {
crash_if_err!(1, writer.write_all(self.line.as_bytes()));
crash_if_err!(1, writer.write_all("\n".as_bytes()));
crash_if_err!(1, writer.write_all(b"\n"));
} else {
crash_if_err!(1, self.print_debug(settings, writer));
}
@ -412,14 +487,18 @@ impl<'a> Line<'a> {
}
}
}
if !(settings.mode == SortMode::Random
|| settings.stable
|| settings.unique
|| !(settings.dictionary_order
if settings.mode != SortMode::Random
&& !settings.stable
&& !settings.unique
&& (settings.dictionary_order
|| settings.ignore_blanks
|| settings.ignore_case
|| settings.ignore_non_printing
|| settings.mode != SortMode::Default))
|| settings.mode != SortMode::Default
|| settings
.selectors
.last()
.map_or(true, |selector| selector != &Default::default()))
{
// A last resort comparator is in use, underline the whole line.
if self.line.is_empty() {
@ -483,7 +562,7 @@ fn tokenize_with_separator(line: &str, separator: char) -> Vec<Field> {
tokens
}
#[derive(Clone)]
#[derive(Clone, PartialEq, Debug)]
struct KeyPosition {
/// 1-indexed, 0 is invalid.
field: usize,
@ -493,87 +572,45 @@ struct KeyPosition {
}
impl KeyPosition {
fn parse(key: &str, default_char_index: usize, settings: &mut KeySettings) -> Self {
fn new(key: &str, default_char_index: usize, ignore_blanks: bool) -> Result<Self, String> {
let mut field_and_char = key.split('.');
let mut field = field_and_char
let field = field_and_char
.next()
.unwrap_or_else(|| crash!(1, "invalid key `{}`", key));
let mut char = field_and_char.next();
// If there is a char index, we expect options to appear after it. Otherwise we expect them after the field index.
let value_with_options = char.as_mut().unwrap_or(&mut field);
let mut ignore_blanks = settings.ignore_blanks;
if let Some(options_start) = value_with_options.chars().position(char::is_alphabetic) {
for option in value_with_options[options_start..].chars() {
// valid options: MbdfghinRrV
match option {
'M' => settings.mode = SortMode::Month,
'b' => ignore_blanks = true,
'd' => settings.dictionary_order = true,
'f' => settings.ignore_case = true,
'g' => settings.mode = SortMode::GeneralNumeric,
'h' => settings.mode = SortMode::HumanNumeric,
'i' => settings.ignore_non_printing = true,
'n' => settings.mode = SortMode::Numeric,
'R' => settings.mode = SortMode::Random,
'r' => settings.reverse = true,
'V' => settings.mode = SortMode::Version,
c => crash!(1, "invalid option for key: `{}`", c),
}
// All numeric sorts and month sort conflict with dictionary_order and ignore_non_printing.
// Instad of reporting an error, let them overwrite each other.
// FIXME: This should only override if the overridden flag is a global flag.
// If conflicting flags are attached to the key, GNU sort crashes and we should probably too.
match option {
'h' | 'n' | 'g' | 'M' => {
settings.dictionary_order = false;
settings.ignore_non_printing = false;
}
'd' | 'i' => {
settings.mode = match settings.mode {
SortMode::Numeric
| SortMode::HumanNumeric
| SortMode::GeneralNumeric
| SortMode::Month => SortMode::Default,
// Only SortMode::Default and SortMode::Version work with dictionary_order and ignore_non_printing
m @ SortMode::Default
| m @ SortMode::Version
| m @ SortMode::Random => m,
}
}
_ => {}
}
}
// Strip away option characters from the original value so we can parse it later
*value_with_options = &value_with_options[..options_start];
}
.ok_or_else(|| format!("invalid key `{}`", key))?;
let char = field_and_char.next();
let field = field
.parse()
.unwrap_or_else(|e| crash!(1, "failed to parse field index for key `{}`: {}", key, e));
.map_err(|e| format!("failed to parse field index `{}`: {}", field, e))?;
if field == 0 {
crash!(1, "field index was 0");
return Err("field index can not be 0".to_string());
}
let char = char.map_or(default_char_index, |char| {
char.parse().unwrap_or_else(|e| {
crash!(
1,
"failed to parse character index for key `{}`: {}",
key,
e
)
})
});
Self {
let char = char.map_or(Ok(default_char_index), |char| {
char.parse()
.map_err(|e| format!("failed to parse character index `{}`: {}", char, e))
})?;
Ok(Self {
field,
char,
ignore_blanks,
})
}
}
impl Default for KeyPosition {
fn default() -> Self {
KeyPosition {
field: 1,
char: 1,
ignore_blanks: false,
}
}
}
#[derive(Clone)]
#[derive(Clone, PartialEq, Debug)]
struct FieldSelector {
from: KeyPosition,
to: Option<KeyPosition>,
@ -583,20 +620,120 @@ struct FieldSelector {
is_default_selection: bool,
}
impl FieldSelector {
fn new(from: KeyPosition, to: Option<KeyPosition>, settings: KeySettings) -> Self {
impl Default for FieldSelector {
fn default() -> Self {
Self {
is_default_selection: from.field == 1
&& from.char == 1
&& to.is_none()
&& !matches!(
settings.mode,
SortMode::Numeric | SortMode::GeneralNumeric | SortMode::HumanNumeric
),
needs_tokens: from.field != 1 || from.char == 0 || to.is_some(),
from,
to,
settings,
from: Default::default(),
to: None,
settings: Default::default(),
needs_tokens: false,
is_default_selection: true,
}
}
}
impl FieldSelector {
/// Splits this position into the actual position and the attached options.
fn split_key_options(position: &str) -> (&str, &str) {
if let Some((options_start, _)) = position.char_indices().find(|(_, c)| c.is_alphabetic()) {
position.split_at(options_start)
} else {
(position, "")
}
}
fn parse(key: &str, global_settings: &GlobalSettings) -> Self {
let mut from_to = key.split(',');
let (from, from_options) = Self::split_key_options(from_to.next().unwrap());
let to = from_to.next().map(|to| Self::split_key_options(to));
let options_are_empty = from_options.is_empty() && matches!(to, None | Some((_, "")));
crash_if_err!(
2,
if options_are_empty {
// Inherit the global settings if there are no options attached to this key.
(|| {
// This would be ideal for a try block, I think. In the meantime this closure allows
// to use the `?` operator here.
Self::new(
KeyPosition::new(from, 1, global_settings.ignore_blanks)?,
to.map(|(to, _)| KeyPosition::new(to, 0, global_settings.ignore_blanks))
.transpose()?,
KeySettings::from(global_settings),
)
})()
} else {
// Do not inherit from `global_settings`, as there are options attached to this key.
Self::parse_with_options((from, from_options), to)
}
.map_err(|e| format!("failed to parse key `{}`: {}", key, e))
)
}
fn parse_with_options(
(from, from_options): (&str, &str),
to: Option<(&str, &str)>,
) -> Result<Self, String> {
/// Applies `options` to `key_settings`, returning if the 'b'-flag (ignore blanks) was present.
fn parse_key_settings(
options: &str,
key_settings: &mut KeySettings,
) -> Result<bool, String> {
let mut ignore_blanks = false;
for option in options.chars() {
match option {
'M' => key_settings.set_sort_mode(SortMode::Month)?,
'b' => ignore_blanks = true,
'd' => key_settings.set_dictionary_order()?,
'f' => key_settings.ignore_case = true,
'g' => key_settings.set_sort_mode(SortMode::GeneralNumeric)?,
'h' => key_settings.set_sort_mode(SortMode::HumanNumeric)?,
'i' => key_settings.set_ignore_non_printing()?,
'n' => key_settings.set_sort_mode(SortMode::Numeric)?,
'R' => key_settings.set_sort_mode(SortMode::Random)?,
'r' => key_settings.reverse = true,
'V' => key_settings.set_sort_mode(SortMode::Version)?,
c => return Err(format!("invalid option: `{}`", c)),
}
}
Ok(ignore_blanks)
}
let mut key_settings = KeySettings::default();
let from = parse_key_settings(from_options, &mut key_settings)
.map(|ignore_blanks| KeyPosition::new(from, 1, ignore_blanks))??;
let to = if let Some((to, to_options)) = to {
Some(
parse_key_settings(to_options, &mut key_settings)
.map(|ignore_blanks| KeyPosition::new(to, 0, ignore_blanks))??,
)
} else {
None
};
Self::new(from, to, key_settings)
}
fn new(
from: KeyPosition,
to: Option<KeyPosition>,
settings: KeySettings,
) -> Result<Self, String> {
if from.char == 0 {
Err("invalid character index 0 for the start position of a field".to_string())
} else {
Ok(Self {
is_default_selection: from.field == 1
&& from.char == 1
&& to.is_none()
&& !matches!(
settings.mode,
SortMode::Numeric | SortMode::GeneralNumeric | SortMode::HumanNumeric
)
&& !from.ignore_blanks,
needs_tokens: from.field != 1 || from.char == 0 || to.is_some(),
from,
to,
settings,
})
}
}
@ -900,7 +1037,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.long(OPT_SEPARATOR)
.help("custom separator for -k")
.takes_value(true))
.arg(Arg::with_name(OPT_ZERO_TERMINATED)
.arg(
Arg::with_name(OPT_ZERO_TERMINATED)
.short("z")
.long(OPT_ZERO_TERMINATED)
.help("line delimiter is NUL, not newline"),
@ -1053,43 +1191,27 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if matches.is_present(OPT_KEY) {
for key in &matches.args[OPT_KEY].vals {
let key = key.to_string_lossy();
let mut from_to = key.split(',');
let mut key_settings = KeySettings::from(&settings);
let from = KeyPosition::parse(
from_to
.next()
.unwrap_or_else(|| crash!(1, "invalid key `{}`", key)),
1,
&mut key_settings,
);
if from.char == 0 {
crash!(
1,
"invalid character index 0 in `{}` for the start position of a field",
key
)
}
let to = from_to
.next()
.map(|to| KeyPosition::parse(to, 0, &mut key_settings));
let field_selector = FieldSelector::new(from, to, key_settings);
settings.selectors.push(field_selector);
settings
.selectors
.push(FieldSelector::parse(&key.to_string_lossy(), &settings));
}
}
if !settings.stable || !matches.is_present(OPT_KEY) {
if !matches.is_present(OPT_KEY) {
// add a default selector matching the whole line
let key_settings = KeySettings::from(&settings);
settings.selectors.push(FieldSelector::new(
KeyPosition {
field: 1,
char: 1,
ignore_blanks: key_settings.ignore_blanks,
},
None,
key_settings,
));
settings.selectors.push(
FieldSelector::new(
KeyPosition {
field: 1,
char: 1,
ignore_blanks: key_settings.ignore_blanks,
},
None,
key_settings,
)
.unwrap(),
);
}
exec(&files, &settings)
@ -1437,7 +1559,7 @@ mod tests {
fn test_get_hash() {
let a = "Ted".to_string();
assert_eq!(2646829031758483623, get_hash(&a));
assert_eq!(2_646_829_031_758_483_623, get_hash(&a));
}
#[test]

View file

@ -200,6 +200,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
split(&settings)
}
#[allow(dead_code)]
struct Settings {
prefix: String,
numeric_suffix: bool,
@ -210,7 +211,7 @@ struct Settings {
filter: Option<String>,
strategy: String,
strategy_param: String,
verbose: bool,
verbose: bool, // TODO: warning: field is never read: `verbose`
}
trait Splitter {

View file

@ -199,6 +199,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
#[allow(clippy::if_same_then_else)]
if matches.is_present(options::FILE_SYSTEM) {
#[cfg(any(target_os = "linux", target_os = "windows"))]
syncfs(files);

View file

@ -265,11 +265,10 @@ impl Parser {
fn boolop(&mut self, op: Symbol) {
if op == Symbol::BoolOp(OsString::from("-a")) {
self.term();
self.stack.push(op);
} else {
self.expr();
self.stack.push(op);
}
self.stack.push(op);
}
/// Parse a (possible) unary argument test (string length or file

View file

@ -145,14 +145,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|| matches.is_present(options::sources::CURRENT)
{
let timestamp = if matches.is_present(options::sources::DATE) {
parse_date(matches.value_of(options::sources::DATE).unwrap().as_ref())
parse_date(matches.value_of(options::sources::DATE).unwrap())
} else {
parse_timestamp(
matches
.value_of(options::sources::CURRENT)
.unwrap()
.as_ref(),
)
parse_timestamp(matches.value_of(options::sources::CURRENT).unwrap())
};
(timestamp, timestamp)
} else {

View file

@ -110,7 +110,7 @@ impl<'a> Iterator for ExpandSet<'a> {
fn next(&mut self) -> Option<Self::Item> {
// while the Range has elements, try to return chars from it
// but make sure that they actually turn out to be Chars!
while let Some(n) = self.range.next() {
for n in &mut self.range {
if let Some(c) = from_u32(n) {
return Some(c);
}

View file

@ -551,10 +551,11 @@ impl Who {
" ?".into()
};
let mut s = ut.host();
if self.do_lookup {
s = safe_unwrap!(ut.canon_host());
}
let s = if self.do_lookup {
safe_unwrap!(ut.canon_host())
} else {
ut.host()
};
let hoststr = if s.is_empty() { s } else { format!("({})", s) };
self.print_line(

View file

@ -179,7 +179,7 @@ impl MountInfo {
/* for Irix 6.5 */
| "ignore" => self.dummy = true,
_ => self.dummy = self.fs_type == "none"
&& self.mount_option.find(MOUNT_OPT_BIND).is_none(),
&& !self.mount_option.contains(MOUNT_OPT_BIND)
}
// set MountInfo::remote
#[cfg(windows)]

View file

@ -40,6 +40,7 @@ pub enum ExitStatus {
Signal(i32),
}
#[allow(clippy::trivially_copy_pass_by_ref)]
impl ExitStatus {
fn from_std_status(status: StdExitStatus) -> Self {
#[cfg(unix)]

View file

@ -146,15 +146,16 @@ pub trait Args: Iterator<Item = OsString> + Sized {
InvalidEncodingHandling::Ignore => s.is_ok(),
_ => true,
})
.map(|s| match s.is_ok() {
true => s.unwrap(),
false => s.unwrap_err(),
.map(|s| match s {
Ok(v) => v,
Err(e) => e,
})
.collect();
match full_conversion {
true => ConversionResult::Complete(result_vector),
false => ConversionResult::Lossy(result_vector),
if full_conversion {
ConversionResult::Complete(result_vector)
} else {
ConversionResult::Lossy(result_vector)
}
}

View file

@ -33,7 +33,7 @@ pub fn determine_backup_suffix(supplied_suffix: Option<&str>) -> String {
if let Some(suffix) = supplied_suffix {
String::from(suffix)
} else {
env::var("SIMPLE_BACKUP_SUFFIX").unwrap_or("~".to_owned())
env::var("SIMPLE_BACKUP_SUFFIX").unwrap_or_else(|_| "~".to_owned())
}
}

View file

@ -34,7 +34,7 @@ fn test_base32_encode_file() {
#[test]
fn test_decode() {
for decode_param in vec!["-d", "--decode"] {
for decode_param in &["-d", "--decode"] {
let input = "JBSWY3DPFQQFO33SNRSCC===\n";
new_ucmd!()
.arg(decode_param)
@ -56,7 +56,7 @@ fn test_garbage() {
#[test]
fn test_ignore_garbage() {
for ignore_garbage_param in vec!["-i", "--ignore-garbage"] {
for ignore_garbage_param in &["-i", "--ignore-garbage"] {
let input = "JBSWY\x013DPFQ\x02QFO33SNRSCC===\n";
new_ucmd!()
.arg("-d")
@ -69,7 +69,7 @@ fn test_ignore_garbage() {
#[test]
fn test_wrap() {
for wrap_param in vec!["-w", "--wrap"] {
for wrap_param in &["-w", "--wrap"] {
let input = "The quick brown fox jumps over the lazy dog.";
new_ucmd!()
.arg(wrap_param)
@ -84,16 +84,21 @@ fn test_wrap() {
#[test]
fn test_wrap_no_arg() {
for wrap_param in vec!["-w", "--wrap"] {
new_ucmd!().arg(wrap_param).fails().stderr_only(format!(
"error: The argument '--wrap <wrap>\' requires a value but none was supplied\n\nUSAGE:\n base32 [OPTION]... [FILE]\n\nFor more information try --help"
));
for wrap_param in &["-w", "--wrap"] {
let expected_stderr = "error: The argument '--wrap <wrap>\' requires a value but none was \
supplied\n\nUSAGE:\n base32 [OPTION]... [FILE]\n\nFor more \
information try --help"
.to_string();
new_ucmd!()
.arg(wrap_param)
.fails()
.stderr_only(expected_stderr);
}
}
#[test]
fn test_wrap_bad_arg() {
for wrap_param in vec!["-w", "--wrap"] {
for wrap_param in &["-w", "--wrap"] {
new_ucmd!()
.arg(wrap_param)
.arg("b")

View file

@ -26,7 +26,7 @@ fn test_base64_encode_file() {
#[test]
fn test_decode() {
for decode_param in vec!["-d", "--decode"] {
for decode_param in &["-d", "--decode"] {
let input = "aGVsbG8sIHdvcmxkIQ==";
new_ucmd!()
.arg(decode_param)
@ -48,7 +48,7 @@ fn test_garbage() {
#[test]
fn test_ignore_garbage() {
for ignore_garbage_param in vec!["-i", "--ignore-garbage"] {
for ignore_garbage_param in &["-i", "--ignore-garbage"] {
let input = "aGVsbG8sIHdvcmxkIQ==\0";
new_ucmd!()
.arg("-d")
@ -61,7 +61,7 @@ fn test_ignore_garbage() {
#[test]
fn test_wrap() {
for wrap_param in vec!["-w", "--wrap"] {
for wrap_param in &["-w", "--wrap"] {
let input = "The quick brown fox jumps over the lazy dog.";
new_ucmd!()
.arg(wrap_param)
@ -74,7 +74,7 @@ fn test_wrap() {
#[test]
fn test_wrap_no_arg() {
for wrap_param in vec!["-w", "--wrap"] {
for wrap_param in &["-w", "--wrap"] {
new_ucmd!().arg(wrap_param).fails().stderr_contains(
&"The argument '--wrap <wrap>' requires a value but none was supplied",
);
@ -83,7 +83,7 @@ fn test_wrap_no_arg() {
#[test]
fn test_wrap_bad_arg() {
for wrap_param in vec!["-w", "--wrap"] {
for wrap_param in &["-w", "--wrap"] {
new_ucmd!()
.arg(wrap_param)
.arg("b")

View file

@ -4,7 +4,7 @@ use std::ffi::OsStr;
#[test]
fn test_help() {
for help_flg in vec!["-h", "--help"] {
for help_flg in &["-h", "--help"] {
new_ucmd!()
.arg(&help_flg)
.succeeds()
@ -15,7 +15,7 @@ fn test_help() {
#[test]
fn test_version() {
for version_flg in vec!["-V", "--version"] {
for version_flg in &["-V", "--version"] {
assert!(new_ucmd!()
.arg(&version_flg)
.succeeds()
@ -59,7 +59,7 @@ fn test_dont_remove_suffix() {
#[test]
fn test_multiple_param() {
for multiple_param in vec!["-a", "--multiple"] {
for &multiple_param in &["-a", "--multiple"] {
let path = "/foo/bar/baz";
new_ucmd!()
.args(&[multiple_param, path, path])
@ -70,7 +70,7 @@ fn test_multiple_param() {
#[test]
fn test_suffix_param() {
for suffix_param in vec!["-s", "--suffix"] {
for &suffix_param in &["-s", "--suffix"] {
let path = "/foo/bar/baz.exe";
new_ucmd!()
.args(&[suffix_param, ".exe", path, path])
@ -81,7 +81,7 @@ fn test_suffix_param() {
#[test]
fn test_zero_param() {
for zero_param in vec!["-z", "--zero"] {
for &zero_param in &["-z", "--zero"] {
let path = "/foo/bar/baz";
new_ucmd!()
.args(&[zero_param, "-a", path, path])
@ -91,7 +91,12 @@ fn test_zero_param() {
}
fn expect_error(input: Vec<&str>) {
assert!(new_ucmd!().args(&input).fails().no_stdout().stderr().len() > 0);
assert!(!new_ucmd!()
.args(&input)
.fails()
.no_stdout()
.stderr_str()
.is_empty());
}
#[test]

View file

@ -237,7 +237,7 @@ fn test_numbered_lines_no_trailing_newline() {
#[test]
fn test_stdin_show_nonprinting() {
for same_param in vec!["-v", "--show-nonprinting"] {
for same_param in &["-v", "--show-nonprinting"] {
new_ucmd!()
.args(&[same_param])
.pipe_in("\t\0\n")
@ -248,7 +248,7 @@ fn test_stdin_show_nonprinting() {
#[test]
fn test_stdin_show_tabs() {
for same_param in vec!["-T", "--show-tabs"] {
for same_param in &["-T", "--show-tabs"] {
new_ucmd!()
.args(&[same_param])
.pipe_in("\t\0\n")
@ -259,7 +259,7 @@ fn test_stdin_show_tabs() {
#[test]
fn test_stdin_show_ends() {
for same_param in vec!["-E", "--show-ends"] {
for &same_param in &["-E", "--show-ends"] {
new_ucmd!()
.args(&[same_param, "-"])
.pipe_in("\t\0\n\t")
@ -270,7 +270,7 @@ fn test_stdin_show_ends() {
#[test]
fn test_stdin_show_all() {
for same_param in vec!["-A", "--show-all"] {
for same_param in &["-A", "--show-all"] {
new_ucmd!()
.args(&[same_param])
.pipe_in("\t\0\n")
@ -299,7 +299,7 @@ fn test_stdin_nonprinting_and_tabs() {
#[test]
fn test_stdin_squeeze_blank() {
for same_param in vec!["-s", "--squeeze-blank"] {
for same_param in &["-s", "--squeeze-blank"] {
new_ucmd!()
.arg(same_param)
.pipe_in("\n\na\n\n\n\n\nb\n\n\n")
@ -310,7 +310,7 @@ fn test_stdin_squeeze_blank() {
#[test]
fn test_stdin_number_non_blank() {
for same_param in vec!["-b", "--number-nonblank"] {
for same_param in &["-b", "--number-nonblank"] {
new_ucmd!()
.arg(same_param)
.arg("-")
@ -322,7 +322,7 @@ fn test_stdin_number_non_blank() {
#[test]
fn test_non_blank_overrides_number() {
for same_param in vec!["-b", "--number-nonblank"] {
for &same_param in &["-b", "--number-nonblank"] {
new_ucmd!()
.args(&[same_param, "-"])
.pipe_in("\na\nb\n\n\nc")
@ -333,7 +333,7 @@ fn test_non_blank_overrides_number() {
#[test]
fn test_squeeze_blank_before_numbering() {
for same_param in vec!["-s", "--squeeze-blank"] {
for &same_param in &["-s", "--squeeze-blank"] {
new_ucmd!()
.args(&[same_param, "-n", "-"])
.pipe_in("a\n\n\nb")
@ -408,7 +408,10 @@ fn test_domain_socket() {
use std::thread;
use unix_socket::UnixListener;
let dir = tempfile::Builder::new().prefix("unix_socket").tempdir().expect("failed to create dir");
let dir = tempfile::Builder::new()
.prefix("unix_socket")
.tempdir()
.expect("failed to create dir");
let socket_path = dir.path().join("sock");
let listener = UnixListener::bind(&socket_path).expect("failed to create socket");
@ -426,7 +429,7 @@ fn test_domain_socket() {
let child = new_ucmd!().args(&[socket_path]).run_no_wait();
barrier.wait();
let stdout = &child.wait_with_output().unwrap().stdout.clone();
let stdout = &child.wait_with_output().unwrap().stdout;
let output = String::from_utf8_lossy(&stdout);
assert_eq!("a\tb", output);

View file

@ -6,7 +6,7 @@ fn test_invalid_option() {
new_ucmd!().arg("-w").arg("/").fails();
}
static DIR: &'static str = "/tmp";
static DIR: &str = "/tmp";
#[test]
fn test_invalid_group() {

View file

@ -8,8 +8,8 @@ use self::chmod::strip_minus_from_mode;
extern crate chmod;
use self::libc::umask;
static TEST_FILE: &'static str = "file";
static REFERENCE_FILE: &'static str = "reference";
static TEST_FILE: &str = "file";
static REFERENCE_FILE: &str = "reference";
static REFERENCE_PERMS: u32 = 0o247;
lazy_static! {
static ref UMASK_MUTEX: Mutex<()> = Mutex::new(());
@ -69,6 +69,7 @@ fn run_tests(tests: Vec<TestCase>) {
}
#[test]
#[allow(clippy::unreadable_literal)]
fn test_chmod_octal() {
let tests = vec![
TestCase {
@ -121,6 +122,7 @@ fn test_chmod_octal() {
}
#[test]
#[allow(clippy::unreadable_literal)]
fn test_chmod_ugoa() {
let _guard = UMASK_MUTEX.lock();
@ -216,6 +218,7 @@ fn test_chmod_ugoa() {
}
#[test]
#[allow(clippy::unreadable_literal)]
fn test_chmod_ugo_copy() {
let tests = vec![
TestCase {
@ -248,6 +251,7 @@ fn test_chmod_ugo_copy() {
}
#[test]
#[allow(clippy::unreadable_literal)]
fn test_chmod_many_options() {
let _guard = UMASK_MUTEX.lock();
@ -264,6 +268,7 @@ fn test_chmod_many_options() {
}
#[test]
#[allow(clippy::unreadable_literal)]
fn test_chmod_reference_file() {
let tests = vec![
TestCase {
@ -303,6 +308,7 @@ fn test_permission_denied() {
}
#[test]
#[allow(clippy::unreadable_literal)]
fn test_chmod_recursive() {
let _guard = UMASK_MUTEX.lock();
@ -477,7 +483,7 @@ fn test_chmod_strip_minus_from_mode() {
];
for test in tests {
let mut args: Vec<String> = test.0.split(" ").map(|v| v.to_string()).collect();
let mut args: Vec<String> = test.0.split(' ').map(|v| v.to_string()).collect();
let _mode_had_minus_prefix = strip_minus_from_mode(&mut args);
assert_eq!(test.1, args.join(" "));
}

View file

@ -39,7 +39,7 @@ mod test_passgrp {
#[test]
fn test_usr2uid() {
assert_eq!(0, usr2uid("root").unwrap());
assert!(usr2uid("88888888").is_err());
assert!(usr2uid("88_888_888").is_err());
assert!(usr2uid("auserthatdoesntexist").is_err());
}
@ -50,14 +50,14 @@ mod test_passgrp {
} else {
assert_eq!(0, grp2gid("wheel").unwrap());
}
assert!(grp2gid("88888888").is_err());
assert!(grp2gid("88_888_888").is_err());
assert!(grp2gid("agroupthatdoesntexist").is_err());
}
#[test]
fn test_uid2usr() {
assert_eq!("root", uid2usr(0).unwrap());
assert!(uid2usr(88888888).is_err());
assert!(uid2usr(88_888_888).is_err());
}
#[test]
@ -67,7 +67,7 @@ mod test_passgrp {
} else {
assert_eq!("wheel", gid2grp(0).unwrap());
}
assert!(gid2grp(88888888).is_err());
assert!(gid2grp(88_888_888).is_err());
}
}

View file

@ -85,12 +85,12 @@ fn test_crc_for_bigger_than_32_bytes() {
let result = ucmd.arg("chars.txt").succeeds();
let mut stdout_splitted = result.stdout_str().split(" ");
let mut stdout_splitted = result.stdout_str().split(' ');
let cksum: i64 = stdout_splitted.next().unwrap().parse().unwrap();
let bytes_cnt: i64 = stdout_splitted.next().unwrap().parse().unwrap();
assert_eq!(cksum, 586047089);
assert_eq!(cksum, 586_047_089);
assert_eq!(bytes_cnt, 16);
}
@ -100,11 +100,11 @@ fn test_stdin_larger_than_128_bytes() {
let result = ucmd.arg("larger_than_2056_bytes.txt").succeeds();
let mut stdout_splitted = result.stdout_str().split(" ");
let mut stdout_splitted = result.stdout_str().split(' ');
let cksum: i64 = stdout_splitted.next().unwrap().parse().unwrap();
let bytes_cnt: i64 = stdout_splitted.next().unwrap().parse().unwrap();
assert_eq!(cksum, 945881979);
assert_eq!(cksum, 945_881_979);
assert_eq!(bytes_cnt, 2058);
}

View file

@ -74,7 +74,7 @@ fn output_delimiter_require_arg() {
#[cfg_attr(not(feature = "test_unimplemented"), ignore)]
#[test]
fn zero_terminated() {
for param in vec!["-z", "--zero-terminated"] {
for &param in &["-z", "--zero-terminated"] {
new_ucmd!()
.args(&[param, "a", "b"])
.fails()

View file

@ -108,7 +108,7 @@ fn test_cp_multiple_files() {
#[test]
// FixME: for MacOS, this has intermittent failures; track repair progress at GH:uutils/coreutils/issues/1590
#[cfg(not(macos))]
#[cfg(not(target_os = "macos"))]
fn test_cp_recurse() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.arg("-r")
@ -132,7 +132,7 @@ fn test_cp_with_dirs_t() {
#[test]
// FixME: for MacOS, this has intermittent failures; track repair progress at GH:uutils/coreutils/issues/1590
#[cfg(not(macos))]
#[cfg(not(target_os = "macos"))]
fn test_cp_with_dirs() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;

View file

@ -1,13 +1,13 @@
use crate::common::util::*;
static INPUT: &'static str = "lists.txt";
static INPUT: &str = "lists.txt";
struct TestedSequence<'b> {
name: &'b str,
sequence: &'b str,
}
static EXAMPLE_SEQUENCES: &'static [TestedSequence<'static>] = &[
static EXAMPLE_SEQUENCES: &[TestedSequence] = &[
TestedSequence {
name: "singular",
sequence: "2",
@ -34,14 +34,14 @@ static EXAMPLE_SEQUENCES: &'static [TestedSequence<'static>] = &[
},
];
static COMPLEX_SEQUENCE: &'static TestedSequence<'static> = &TestedSequence {
static COMPLEX_SEQUENCE: &TestedSequence = &TestedSequence {
name: "",
sequence: "9-,6-7,-2,4",
};
#[test]
fn test_byte_sequence() {
for param in vec!["-b", "--bytes"] {
for &param in &["-b", "--bytes"] {
for example_seq in EXAMPLE_SEQUENCES {
new_ucmd!()
.args(&[param, example_seq.sequence, INPUT])
@ -53,7 +53,7 @@ fn test_byte_sequence() {
#[test]
fn test_char_sequence() {
for param in vec!["-c", "--characters"] {
for &param in &["-c", "--characters"] {
for example_seq in EXAMPLE_SEQUENCES {
//as of coreutils 8.25 a char range is effectively the same as a byte range; there is no distinct treatment of utf8 chars.
new_ucmd!()
@ -66,7 +66,7 @@ fn test_char_sequence() {
#[test]
fn test_field_sequence() {
for param in vec!["-f", "--fields"] {
for &param in &["-f", "--fields"] {
for example_seq in EXAMPLE_SEQUENCES {
new_ucmd!()
.args(&[param, example_seq.sequence, INPUT])
@ -78,7 +78,7 @@ fn test_field_sequence() {
#[test]
fn test_specify_delimiter() {
for param in vec!["-d", "--delimiter"] {
for &param in &["-d", "--delimiter"] {
new_ucmd!()
.args(&[param, ":", "-f", COMPLEX_SEQUENCE.sequence, INPUT])
.succeeds()
@ -122,7 +122,7 @@ fn test_zero_terminated() {
#[test]
fn test_only_delimited() {
for param in vec!["-s", "--only-delimited"] {
for param in &["-s", "--only-delimited"] {
new_ucmd!()
.args(&["-d_", param, "-f", "1"])
.pipe_in("91\n82\n7_3")

View file

@ -187,7 +187,7 @@ fn test_du_d_flag() {
// TODO: gnu `du` doesn't use trailing "/" here
// result.stdout_str(), result_reference.stdout_str()
result.stdout_str().trim_end_matches("/\n"),
result_reference.stdout_str().trim_end_matches("\n")
result_reference.stdout_str().trim_end_matches('\n')
);
return;
}

View file

@ -118,7 +118,7 @@ fn test_null_delimiter() {
let mut vars: Vec<_> = out.split('\0').collect();
assert_eq!(vars.len(), 3);
vars.sort();
vars.sort_unstable();
assert_eq!(vars[0], "");
assert_eq!(vars[1], "ABC=xyz");
assert_eq!(vars[2], "FOO=bar");
@ -135,7 +135,7 @@ fn test_unset_variable() {
.succeeds()
.stdout_move_str();
assert_eq!(out.lines().any(|line| line.starts_with("HOME=")), false);
assert!(!out.lines().any(|line| line.starts_with("HOME=")));
}
#[test]
@ -196,7 +196,7 @@ fn test_change_directory() {
fn test_fail_change_directory() {
let scene = TestScenario::new(util_name!());
let some_non_existing_path = "some_nonexistent_path";
assert_eq!(Path::new(some_non_existing_path).is_dir(), false);
assert!(!Path::new(some_non_existing_path).is_dir());
let out = scene
.ucmd()

View file

@ -2,55 +2,95 @@ use crate::common::util::*;
#[test]
fn test_simple_arithmetic() {
new_ucmd!().args(&["1", "+", "1"]).run().stdout_is("2\n");
new_ucmd!()
.args(&["1", "+", "1"])
.succeeds()
.stdout_only("2\n");
new_ucmd!().args(&["1", "-", "1"]).run().stdout_is("0\n");
new_ucmd!()
.args(&["1", "-", "1"])
.fails()
.status_code(1)
.stdout_only("0\n");
new_ucmd!().args(&["3", "*", "2"]).run().stdout_is("6\n");
new_ucmd!()
.args(&["3", "*", "2"])
.succeeds()
.stdout_only("6\n");
new_ucmd!().args(&["4", "/", "2"]).run().stdout_is("2\n");
new_ucmd!()
.args(&["4", "/", "2"])
.succeeds()
.stdout_only("2\n");
}
#[test]
fn test_complex_arithmetic() {
let run = new_ucmd!()
new_ucmd!()
.args(&["9223372036854775807", "+", "9223372036854775807"])
.run();
run.stdout_is("");
run.stderr_is("expr: +: Numerical result out of range");
.succeeds()
.stdout_only("18446744073709551614\n");
let run = new_ucmd!().args(&["9", "/", "0"]).run();
run.stdout_is("");
run.stderr_is("expr: division by zero");
new_ucmd!()
.args(&[
"92233720368547758076549841651981984981498415651",
"%",
"922337203685",
])
.succeeds()
.stdout_only("533691697086\n");
new_ucmd!()
.args(&[
"92233720368547758076549841651981984981498415651",
"*",
"922337203685",
])
.succeeds()
.stdout_only("85070591730190566808700855121818604965830915152801178873935\n");
new_ucmd!()
.args(&[
"92233720368547758076549841651981984981498415651",
"-",
"922337203685",
])
.succeeds()
.stdout_only("92233720368547758076549841651981984059161211966\n");
new_ucmd!()
.args(&["9", "/", "0"])
.fails()
.stderr_only("expr: division by zero\n");
}
#[test]
fn test_parenthesis() {
new_ucmd!()
.args(&["(", "1", "+", "1", ")", "*", "2"])
.run()
.stdout_is("4\n");
.succeeds()
.stdout_only("4\n");
}
#[test]
fn test_or() {
new_ucmd!()
.args(&["0", "|", "foo"])
.run()
.stdout_is("foo\n");
.succeeds()
.stdout_only("foo\n");
new_ucmd!()
.args(&["foo", "|", "bar"])
.run()
.stdout_is("foo\n");
.succeeds()
.stdout_only("foo\n");
}
#[test]
fn test_and() {
new_ucmd!()
.args(&["foo", "&", "1"])
.run()
.stdout_is("foo\n");
.succeeds()
.stdout_only("foo\n");
new_ucmd!().args(&["", "&", "1"]).run().stdout_is("0\n");
}

View file

@ -4,6 +4,7 @@
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.
#![allow(clippy::unreadable_literal)]
use crate::common::util::*;
use std::time::SystemTime;
@ -89,7 +90,7 @@ fn test_random() {
};
}
factors.sort();
factors.sort_unstable();
(product, factors)
};
@ -104,7 +105,7 @@ fn test_random() {
for factor in factors {
outstring.push_str(&(format!(" {}", factor))[..]);
}
outstring.push_str("\n");
outstring.push('\n');
}
run(instring.as_bytes(), outstring.as_bytes());
@ -143,7 +144,7 @@ fn test_random_big() {
f_bits.push(extrarange.sample(&mut rng));
}
f_bits.push(extrabits);
f_bits.sort();
f_bits.sort_unstable();
// compute sequential differences here. We leave off the +14 bits
// so we can just index PRIMES_BY_BITS
@ -172,7 +173,7 @@ fn test_random_big() {
}
assert_eq!(nbits, 64);
factors.sort();
factors.sort_unstable();
(product, factors)
};
@ -186,7 +187,7 @@ fn test_random_big() {
for factor in factors {
outstring.push_str(&(format!(" {}", factor))[..]);
}
outstring.push_str("\n");
outstring.push('\n');
}
run(instring.as_bytes(), outstring.as_bytes());
@ -214,7 +215,7 @@ fn run(instring: &[u8], outstring: &[u8]) {
.stdout_is(String::from_utf8(outstring.to_owned()).unwrap());
}
const PRIMES_BY_BITS: &'static [&'static [u64]] = &[
const PRIMES_BY_BITS: &[&[u64]] = &[
PRIMES14, PRIMES15, PRIMES16, PRIMES17, PRIMES18, PRIMES19, PRIMES20, PRIMES21, PRIMES22,
PRIMES23, PRIMES24, PRIMES25, PRIMES26, PRIMES27, PRIMES28, PRIMES29, PRIMES30, PRIMES31,
PRIMES32, PRIMES33, PRIMES34, PRIMES35, PRIMES36, PRIMES37, PRIMES38, PRIMES39, PRIMES40,
@ -222,7 +223,7 @@ const PRIMES_BY_BITS: &'static [&'static [u64]] = &[
PRIMES50,
];
const PRIMES64: &'static [u64] = &[
const PRIMES64: &[u64] = &[
18446744073709551557,
18446744073709551533,
18446744073709551521,
@ -274,7 +275,7 @@ const PRIMES64: &'static [u64] = &[
18446744073709549571,
];
const PRIMES14: &'static [u64] = &[
const PRIMES14: &[u64] = &[
16381, 16369, 16363, 16361, 16349, 16339, 16333, 16319, 16301, 16273, 16267, 16253, 16249,
16231, 16229, 16223, 16217, 16193, 16189, 16187, 16183, 16141, 16139, 16127, 16111, 16103,
16097, 16091, 16087, 16073, 16069, 16067, 16063, 16061, 16057, 16033, 16007, 16001, 15991,
@ -286,7 +287,7 @@ const PRIMES14: &'static [u64] = &[
15373,
];
const PRIMES15: &'static [u64] = &[
const PRIMES15: &[u64] = &[
32749, 32719, 32717, 32713, 32707, 32693, 32687, 32653, 32647, 32633, 32621, 32611, 32609,
32603, 32587, 32579, 32573, 32569, 32563, 32561, 32537, 32533, 32531, 32507, 32503, 32497,
32491, 32479, 32467, 32443, 32441, 32429, 32423, 32413, 32411, 32401, 32381, 32377, 32371,
@ -297,7 +298,7 @@ const PRIMES15: &'static [u64] = &[
31847, 31817, 31799, 31793, 31771, 31769, 31751,
];
const PRIMES16: &'static [u64] = &[
const PRIMES16: &[u64] = &[
65521, 65519, 65497, 65479, 65449, 65447, 65437, 65423, 65419, 65413, 65407, 65393, 65381,
65371, 65357, 65353, 65327, 65323, 65309, 65293, 65287, 65269, 65267, 65257, 65239, 65213,
65203, 65183, 65179, 65173, 65171, 65167, 65147, 65141, 65129, 65123, 65119, 65111, 65101,
@ -307,7 +308,7 @@ const PRIMES16: &'static [u64] = &[
64627, 64621, 64613, 64609, 64601, 64591, 64579, 64577, 64567, 64553,
];
const PRIMES17: &'static [u64] = &[
const PRIMES17: &[u64] = &[
131071, 131063, 131059, 131041, 131023, 131011, 131009, 130987, 130981, 130973, 130969, 130957,
130927, 130873, 130859, 130843, 130841, 130829, 130817, 130811, 130807, 130787, 130783, 130769,
130729, 130699, 130693, 130687, 130681, 130657, 130651, 130649, 130643, 130639, 130633, 130631,
@ -318,7 +319,7 @@ const PRIMES17: &'static [u64] = &[
130073, 130069, 130057, 130051,
];
const PRIMES18: &'static [u64] = &[
const PRIMES18: &[u64] = &[
262139, 262133, 262127, 262121, 262111, 262109, 262103, 262079, 262069, 262051, 262049, 262027,
262007, 261983, 261977, 261973, 261971, 261959, 261917, 261887, 261881, 261847, 261823, 261799,
261791, 261787, 261773, 261761, 261757, 261739, 261721, 261713, 261707, 261697, 261673, 261643,
@ -328,7 +329,7 @@ const PRIMES18: &'static [u64] = &[
261169, 261167, 261127,
];
const PRIMES19: &'static [u64] = &[
const PRIMES19: &[u64] = &[
524287, 524269, 524261, 524257, 524243, 524231, 524221, 524219, 524203, 524201, 524197, 524189,
524171, 524149, 524123, 524119, 524113, 524099, 524087, 524081, 524071, 524063, 524057, 524053,
524047, 523997, 523987, 523969, 523949, 523937, 523927, 523907, 523903, 523877, 523867, 523847,
@ -338,7 +339,7 @@ const PRIMES19: &'static [u64] = &[
523403, 523387, 523357, 523351, 523349, 523333, 523307, 523297,
];
const PRIMES20: &'static [u64] = &[
const PRIMES20: &[u64] = &[
1048573, 1048571, 1048559, 1048549, 1048517, 1048507, 1048447, 1048433, 1048423, 1048391,
1048387, 1048367, 1048361, 1048357, 1048343, 1048309, 1048291, 1048273, 1048261, 1048219,
1048217, 1048213, 1048193, 1048189, 1048139, 1048129, 1048127, 1048123, 1048063, 1048051,
@ -348,7 +349,7 @@ const PRIMES20: &'static [u64] = &[
1047691, 1047689, 1047671, 1047667, 1047653, 1047649, 1047647, 1047589, 1047587, 1047559,
];
const PRIMES21: &'static [u64] = &[
const PRIMES21: &[u64] = &[
2097143, 2097133, 2097131, 2097097, 2097091, 2097083, 2097047, 2097041, 2097031, 2097023,
2097013, 2096993, 2096987, 2096971, 2096959, 2096957, 2096947, 2096923, 2096911, 2096909,
2096893, 2096881, 2096873, 2096867, 2096851, 2096837, 2096807, 2096791, 2096789, 2096777,
@ -358,7 +359,7 @@ const PRIMES21: &'static [u64] = &[
2096221, 2096209, 2096191, 2096183, 2096147,
];
const PRIMES22: &'static [u64] = &[
const PRIMES22: &[u64] = &[
4194301, 4194287, 4194277, 4194271, 4194247, 4194217, 4194199, 4194191, 4194187, 4194181,
4194173, 4194167, 4194143, 4194137, 4194131, 4194107, 4194103, 4194023, 4194011, 4194007,
4193977, 4193971, 4193963, 4193957, 4193939, 4193929, 4193909, 4193869, 4193807, 4193803,
@ -368,7 +369,7 @@ const PRIMES22: &'static [u64] = &[
4193297,
];
const PRIMES23: &'static [u64] = &[
const PRIMES23: &[u64] = &[
8388593, 8388587, 8388581, 8388571, 8388547, 8388539, 8388473, 8388461, 8388451, 8388449,
8388439, 8388427, 8388421, 8388409, 8388377, 8388371, 8388319, 8388301, 8388287, 8388283,
8388277, 8388239, 8388209, 8388187, 8388113, 8388109, 8388091, 8388071, 8388059, 8388019,
@ -377,7 +378,7 @@ const PRIMES23: &'static [u64] = &[
8387723, 8387707, 8387671, 8387611, 8387609, 8387591,
];
const PRIMES24: &'static [u64] = &[
const PRIMES24: &[u64] = &[
16777213, 16777199, 16777183, 16777153, 16777141, 16777139, 16777127, 16777121, 16777099,
16777049, 16777027, 16776989, 16776973, 16776971, 16776967, 16776961, 16776941, 16776937,
16776931, 16776919, 16776901, 16776899, 16776869, 16776857, 16776839, 16776833, 16776817,
@ -387,7 +388,7 @@ const PRIMES24: &'static [u64] = &[
16776317, 16776313, 16776289, 16776217, 16776211,
];
const PRIMES25: &'static [u64] = &[
const PRIMES25: &[u64] = &[
33554393, 33554383, 33554371, 33554347, 33554341, 33554317, 33554291, 33554273, 33554267,
33554249, 33554239, 33554221, 33554201, 33554167, 33554159, 33554137, 33554123, 33554093,
33554083, 33554077, 33554051, 33554021, 33554011, 33554009, 33553999, 33553991, 33553969,
@ -397,7 +398,7 @@ const PRIMES25: &'static [u64] = &[
33553519, 33553517, 33553511, 33553489, 33553463, 33553451, 33553417,
];
const PRIMES26: &'static [u64] = &[
const PRIMES26: &[u64] = &[
67108859, 67108837, 67108819, 67108777, 67108763, 67108757, 67108753, 67108747, 67108739,
67108729, 67108721, 67108709, 67108693, 67108669, 67108667, 67108661, 67108649, 67108633,
67108597, 67108579, 67108529, 67108511, 67108507, 67108493, 67108471, 67108463, 67108453,
@ -408,7 +409,7 @@ const PRIMES26: &'static [u64] = &[
67107863,
];
const PRIMES27: &'static [u64] = &[
const PRIMES27: &[u64] = &[
134217689, 134217649, 134217617, 134217613, 134217593, 134217541, 134217529, 134217509,
134217497, 134217493, 134217487, 134217467, 134217439, 134217437, 134217409, 134217403,
134217401, 134217367, 134217361, 134217353, 134217323, 134217301, 134217277, 134217257,
@ -419,7 +420,7 @@ const PRIMES27: &'static [u64] = &[
134216737, 134216729,
];
const PRIMES28: &'static [u64] = &[
const PRIMES28: &[u64] = &[
268435399, 268435367, 268435361, 268435337, 268435331, 268435313, 268435291, 268435273,
268435243, 268435183, 268435171, 268435157, 268435147, 268435133, 268435129, 268435121,
268435109, 268435091, 268435067, 268435043, 268435039, 268435033, 268435019, 268435009,
@ -430,7 +431,7 @@ const PRIMES28: &'static [u64] = &[
268434479, 268434461,
];
const PRIMES29: &'static [u64] = &[
const PRIMES29: &[u64] = &[
536870909, 536870879, 536870869, 536870849, 536870839, 536870837, 536870819, 536870813,
536870791, 536870779, 536870767, 536870743, 536870729, 536870723, 536870717, 536870701,
536870683, 536870657, 536870641, 536870627, 536870611, 536870603, 536870599, 536870573,
@ -440,7 +441,7 @@ const PRIMES29: &'static [u64] = &[
536870027, 536869999, 536869951, 536869943, 536869937, 536869919, 536869901, 536869891,
];
const PRIMES30: &'static [u64] = &[
const PRIMES30: &[u64] = &[
1073741789, 1073741783, 1073741741, 1073741723, 1073741719, 1073741717, 1073741689, 1073741671,
1073741663, 1073741651, 1073741621, 1073741567, 1073741561, 1073741527, 1073741503, 1073741477,
1073741467, 1073741441, 1073741419, 1073741399, 1073741387, 1073741381, 1073741371, 1073741329,
@ -449,7 +450,7 @@ const PRIMES30: &'static [u64] = &[
1073740853, 1073740847, 1073740819, 1073740807,
];
const PRIMES31: &'static [u64] = &[
const PRIMES31: &[u64] = &[
2147483647, 2147483629, 2147483587, 2147483579, 2147483563, 2147483549, 2147483543, 2147483497,
2147483489, 2147483477, 2147483423, 2147483399, 2147483353, 2147483323, 2147483269, 2147483249,
2147483237, 2147483179, 2147483171, 2147483137, 2147483123, 2147483077, 2147483069, 2147483059,
@ -458,7 +459,7 @@ const PRIMES31: &'static [u64] = &[
2147482763, 2147482739, 2147482697, 2147482693, 2147482681, 2147482663, 2147482661,
];
const PRIMES32: &'static [u64] = &[
const PRIMES32: &[u64] = &[
4294967291, 4294967279, 4294967231, 4294967197, 4294967189, 4294967161, 4294967143, 4294967111,
4294967087, 4294967029, 4294966997, 4294966981, 4294966943, 4294966927, 4294966909, 4294966877,
4294966829, 4294966813, 4294966769, 4294966667, 4294966661, 4294966657, 4294966651, 4294966639,
@ -466,7 +467,7 @@ const PRIMES32: &'static [u64] = &[
4294966373, 4294966367, 4294966337, 4294966297,
];
const PRIMES33: &'static [u64] = &[
const PRIMES33: &[u64] = &[
8589934583, 8589934567, 8589934543, 8589934513, 8589934487, 8589934307, 8589934291, 8589934289,
8589934271, 8589934237, 8589934211, 8589934207, 8589934201, 8589934187, 8589934151, 8589934141,
8589934139, 8589934117, 8589934103, 8589934099, 8589934091, 8589934069, 8589934049, 8589934027,
@ -475,7 +476,7 @@ const PRIMES33: &'static [u64] = &[
8589933647, 8589933641, 8589933637, 8589933631, 8589933629, 8589933619, 8589933601, 8589933581,
];
const PRIMES34: &'static [u64] = &[
const PRIMES34: &[u64] = &[
17179869143,
17179869107,
17179869071,
@ -526,7 +527,7 @@ const PRIMES34: &'static [u64] = &[
17179868183,
];
const PRIMES35: &'static [u64] = &[
const PRIMES35: &[u64] = &[
34359738337,
34359738319,
34359738307,
@ -559,7 +560,7 @@ const PRIMES35: &'static [u64] = &[
34359737371,
];
const PRIMES36: &'static [u64] = &[
const PRIMES36: &[u64] = &[
68719476731,
68719476719,
68719476713,
@ -611,7 +612,7 @@ const PRIMES36: &'static [u64] = &[
68719475729,
];
const PRIMES37: &'static [u64] = &[
const PRIMES37: &[u64] = &[
137438953447,
137438953441,
137438953427,
@ -637,7 +638,7 @@ const PRIMES37: &'static [u64] = &[
137438952491,
];
const PRIMES38: &'static [u64] = &[
const PRIMES38: &[u64] = &[
274877906899,
274877906857,
274877906837,
@ -677,7 +678,7 @@ const PRIMES38: &'static [u64] = &[
274877905931,
];
const PRIMES39: &'static [u64] = &[
const PRIMES39: &[u64] = &[
549755813881,
549755813869,
549755813821,
@ -723,7 +724,7 @@ const PRIMES39: &'static [u64] = &[
549755812867,
];
const PRIMES40: &'static [u64] = &[
const PRIMES40: &[u64] = &[
1099511627689,
1099511627609,
1099511627581,
@ -753,7 +754,7 @@ const PRIMES40: &'static [u64] = &[
1099511626771,
];
const PRIMES41: &'static [u64] = &[
const PRIMES41: &[u64] = &[
2199023255531,
2199023255521,
2199023255497,
@ -792,7 +793,7 @@ const PRIMES41: &'static [u64] = &[
2199023254567,
];
const PRIMES42: &'static [u64] = &[
const PRIMES42: &[u64] = &[
4398046511093,
4398046511087,
4398046511071,
@ -832,7 +833,7 @@ const PRIMES42: &'static [u64] = &[
4398046510093,
];
const PRIMES43: &'static [u64] = &[
const PRIMES43: &[u64] = &[
8796093022151,
8796093022141,
8796093022091,
@ -867,7 +868,7 @@ const PRIMES43: &'static [u64] = &[
8796093021269,
];
const PRIMES44: &'static [u64] = &[
const PRIMES44: &[u64] = &[
17592186044399,
17592186044299,
17592186044297,
@ -900,7 +901,7 @@ const PRIMES44: &'static [u64] = &[
17592186043409,
];
const PRIMES45: &'static [u64] = &[
const PRIMES45: &[u64] = &[
35184372088777,
35184372088763,
35184372088751,
@ -941,7 +942,7 @@ const PRIMES45: &'static [u64] = &[
35184372087869,
];
const PRIMES46: &'static [u64] = &[
const PRIMES46: &[u64] = &[
70368744177643,
70368744177607,
70368744177601,
@ -976,7 +977,7 @@ const PRIMES46: &'static [u64] = &[
70368744176711,
];
const PRIMES47: &'static [u64] = &[
const PRIMES47: &[u64] = &[
140737488355213,
140737488355201,
140737488355181,
@ -998,7 +999,7 @@ const PRIMES47: &'static [u64] = &[
140737488354329,
];
const PRIMES48: &'static [u64] = &[
const PRIMES48: &[u64] = &[
281474976710597,
281474976710591,
281474976710567,
@ -1031,7 +1032,7 @@ const PRIMES48: &'static [u64] = &[
281474976709637,
];
const PRIMES49: &'static [u64] = &[
const PRIMES49: &[u64] = &[
562949953421231,
562949953421201,
562949953421189,
@ -1065,7 +1066,7 @@ const PRIMES49: &'static [u64] = &[
562949953420297,
];
const PRIMES50: &'static [u64] = &[
const PRIMES50: &[u64] = &[
1125899906842597,
1125899906842589,
1125899906842573,

View file

@ -1,6 +1,6 @@
use crate::common::util::*;
static INPUT: &'static str = "lorem_ipsum.txt";
static INPUT: &str = "lorem_ipsum.txt";
#[test]
fn test_stdin_default() {

View file

@ -116,11 +116,11 @@ fn test_install_ancestors_mode_directories() {
assert!(at.dir_exists(ancestor2));
assert!(at.dir_exists(target_dir));
assert_ne!(0o40700 as u32, at.metadata(ancestor1).permissions().mode());
assert_ne!(0o40700 as u32, at.metadata(ancestor2).permissions().mode());
assert_ne!(0o40_700_u32, at.metadata(ancestor1).permissions().mode());
assert_ne!(0o40_700_u32, at.metadata(ancestor2).permissions().mode());
// Expected mode only on the target_dir.
assert_eq!(0o40700 as u32, at.metadata(target_dir).permissions().mode());
assert_eq!(0o40_700_u32, at.metadata(target_dir).permissions().mode());
}
#[test]
@ -184,7 +184,7 @@ fn test_install_mode_numeric() {
assert!(at.file_exists(file));
assert!(at.file_exists(dest_file));
let permissions = at.metadata(dest_file).permissions();
assert_eq!(0o100333 as u32, PermissionsExt::mode(&permissions));
assert_eq!(0o100_333_u32, PermissionsExt::mode(&permissions));
let mode_arg = "-m 0333";
at.mkdir(dir2);
@ -195,7 +195,7 @@ fn test_install_mode_numeric() {
assert!(at.file_exists(file));
assert!(at.file_exists(dest_file));
let permissions = at.metadata(dest_file).permissions();
assert_eq!(0o100333 as u32, PermissionsExt::mode(&permissions));
assert_eq!(0o100_333_u32, PermissionsExt::mode(&permissions));
}
#[test]
@ -213,7 +213,7 @@ fn test_install_mode_symbolic() {
assert!(at.file_exists(file));
assert!(at.file_exists(dest_file));
let permissions = at.metadata(dest_file).permissions();
assert_eq!(0o100003 as u32, PermissionsExt::mode(&permissions));
assert_eq!(0o100_003_u32, PermissionsExt::mode(&permissions));
}
#[test]
@ -251,7 +251,7 @@ fn test_install_mode_directories() {
assert!(at.dir_exists(component));
let permissions = at.metadata(component).permissions();
assert_eq!(0o040333 as u32, PermissionsExt::mode(&permissions));
assert_eq!(0o040_333_u32, PermissionsExt::mode(&permissions));
}
#[test]

View file

@ -51,6 +51,7 @@ fn test_ls_a() {
.unwrap(),
);
#[allow(clippy::trivial_regex)]
let re_pwd = Regex::new(r"^\.\n").unwrap();
// Using the present working directory
@ -124,7 +125,7 @@ fn test_ls_width() {
for option in &["-w 100", "-w=100", "--width=100", "--width 100"] {
scene
.ucmd()
.args(&option.split(" ").collect::<Vec<_>>())
.args(&option.split(' ').collect::<Vec<_>>())
.succeeds()
.stdout_only("test-width-1 test-width-2 test-width-3 test-width-4\n");
}
@ -132,7 +133,7 @@ fn test_ls_width() {
for option in &["-w 50", "-w=50", "--width=50", "--width 50"] {
scene
.ucmd()
.args(&option.split(" ").collect::<Vec<_>>())
.args(&option.split(' ').collect::<Vec<_>>())
.succeeds()
.stdout_only("test-width-1 test-width-3\ntest-width-2 test-width-4\n");
}
@ -149,7 +150,7 @@ fn test_ls_width() {
] {
scene
.ucmd()
.args(&option.split(" ").collect::<Vec<_>>())
.args(&option.split(' ').collect::<Vec<_>>())
.succeeds()
.stdout_only("test-width-1\ntest-width-2\ntest-width-3\ntest-width-4\n");
}
@ -163,7 +164,7 @@ fn test_ls_width() {
for option in &["-w 1a", "-w=1a", "--width=1a", "--width 1a"] {
scene
.ucmd()
.args(&option.split(" ").collect::<Vec<_>>())
.args(&option.split(' ').collect::<Vec<_>>())
.fails()
.stderr_only("ls: invalid line width: 1a");
}
@ -417,7 +418,7 @@ fn test_ls_long_formats() {
] {
let result = scene
.ucmd()
.args(&arg.split(" ").collect::<Vec<_>>())
.args(&arg.split(' ').collect::<Vec<_>>())
.arg("test-long-formats")
.succeeds();
assert!(re_two.is_match(result.stdout_str()));
@ -427,7 +428,7 @@ fn test_ls_long_formats() {
let result = scene
.ucmd()
.arg("-n")
.args(&arg.split(" ").collect::<Vec<_>>())
.args(&arg.split(' ').collect::<Vec<_>>())
.arg("test-long-formats")
.succeeds();
assert!(re_two_num.is_match(result.stdout_str()));
@ -446,7 +447,7 @@ fn test_ls_long_formats() {
] {
let result = scene
.ucmd()
.args(&arg.split(" ").collect::<Vec<_>>())
.args(&arg.split(' ').collect::<Vec<_>>())
.arg("test-long-formats")
.succeeds();
assert!(re_one.is_match(result.stdout_str()));
@ -456,7 +457,7 @@ fn test_ls_long_formats() {
let result = scene
.ucmd()
.arg("-n")
.args(&arg.split(" ").collect::<Vec<_>>())
.args(&arg.split(' ').collect::<Vec<_>>())
.arg("test-long-formats")
.succeeds();
assert!(re_one_num.is_match(result.stdout_str()));
@ -478,7 +479,7 @@ fn test_ls_long_formats() {
] {
let result = scene
.ucmd()
.args(&arg.split(" ").collect::<Vec<_>>())
.args(&arg.split(' ').collect::<Vec<_>>())
.arg("test-long-formats")
.succeeds();
assert!(re_zero.is_match(result.stdout_str()));
@ -488,7 +489,7 @@ fn test_ls_long_formats() {
let result = scene
.ucmd()
.arg("-n")
.args(&arg.split(" ").collect::<Vec<_>>())
.args(&arg.split(' ').collect::<Vec<_>>())
.arg("test-long-formats")
.succeeds();
assert!(re_zero.is_match(result.stdout_str()));
@ -898,6 +899,12 @@ fn test_ls_recursive() {
scene.ucmd().arg("a").succeeds();
scene.ucmd().arg("a/a").succeeds();
scene
.ucmd()
.arg("z")
.arg("-R")
.succeeds()
.stdout_contains(&"z:");
let result = scene
.ucmd()
.arg("--color=never")
@ -1063,7 +1070,7 @@ fn test_ls_indicator_style() {
for opt in options {
scene
.ucmd()
.arg(format!("{}", opt))
.arg(opt.to_string())
.succeeds()
.stdout_contains(&"/");
}
@ -1085,7 +1092,10 @@ fn test_ls_indicator_style() {
{
use self::unix_socket::UnixListener;
let dir = tempfile::Builder::new().prefix("unix_socket").tempdir().expect("failed to create dir");
let dir = tempfile::Builder::new()
.prefix("unix_socket")
.tempdir()
.expect("failed to create dir");
let socket_path = dir.path().join("sock");
let _listener = UnixListener::bind(&socket_path).expect("failed to create socket");

View file

@ -1,12 +1,12 @@
use crate::common::util::*;
static TEST_DIR1: &'static str = "mkdir_test1";
static TEST_DIR2: &'static str = "mkdir_test2";
static TEST_DIR3: &'static str = "mkdir_test3";
static TEST_DIR4: &'static str = "mkdir_test4/mkdir_test4_1";
static TEST_DIR5: &'static str = "mkdir_test5/mkdir_test5_1";
static TEST_DIR6: &'static str = "mkdir_test6";
static TEST_FILE7: &'static str = "mkdir_test7";
static TEST_DIR1: &str = "mkdir_test1";
static TEST_DIR2: &str = "mkdir_test2";
static TEST_DIR3: &str = "mkdir_test3";
static TEST_DIR4: &str = "mkdir_test4/mkdir_test4_1";
static TEST_DIR5: &str = "mkdir_test5/mkdir_test5_1";
static TEST_DIR6: &str = "mkdir_test6";
static TEST_FILE7: &str = "mkdir_test7";
#[test]
fn test_mkdir_mkdir() {

View file

@ -3,19 +3,19 @@ use crate::common::util::*;
use std::path::PathBuf;
use tempfile::tempdir;
static TEST_TEMPLATE1: &'static str = "tempXXXXXX";
static TEST_TEMPLATE2: &'static str = "temp";
static TEST_TEMPLATE3: &'static str = "tempX";
static TEST_TEMPLATE4: &'static str = "tempXX";
static TEST_TEMPLATE5: &'static str = "tempXXX";
static TEST_TEMPLATE6: &'static str = "tempXXXlate";
static TEST_TEMPLATE7: &'static str = "XXXtemplate";
static TEST_TEMPLATE1: &str = "tempXXXXXX";
static TEST_TEMPLATE2: &str = "temp";
static TEST_TEMPLATE3: &str = "tempX";
static TEST_TEMPLATE4: &str = "tempXX";
static TEST_TEMPLATE5: &str = "tempXXX";
static TEST_TEMPLATE6: &str = "tempXXXlate";
static TEST_TEMPLATE7: &str = "XXXtemplate";
#[cfg(unix)]
static TEST_TEMPLATE8: &'static str = "tempXXXl/ate";
static TEST_TEMPLATE8: &str = "tempXXXl/ate";
#[cfg(windows)]
static TEST_TEMPLATE8: &'static str = "tempXXXl\\ate";
static TEST_TEMPLATE8: &str = "tempXXXl\\ate";
const TMPDIR: &'static str = "TMPDIR";
const TMPDIR: &str = "TMPDIR";
#[test]
fn test_mktemp_mktemp() {

View file

@ -2,15 +2,22 @@ use crate::common::util::*;
#[test]
fn test_more_no_arg() {
// stderr = more: Reading from stdin isn't supported yet.
new_ucmd!().fails();
// Reading from stdin is now supported, so this must succeed
if atty::is(atty::Stream::Stdout) {
new_ucmd!().succeeds();
} else {}
}
#[test]
fn test_more_dir_arg() {
let result = new_ucmd!().arg(".").run();
result.failure();
const EXPECTED_ERROR_MESSAGE: &str =
"more: '.' is a directory.\nTry 'more --help' for more information.";
assert_eq!(result.stderr_str().trim(), EXPECTED_ERROR_MESSAGE);
// Run the test only if there's a valud terminal, else do nothing
// Maybe we could capture the error, i.e. "Device not found" in that case
// but I am leaving this for later
if atty::is(atty::Stream::Stdout) {
let result = new_ucmd!().arg(".").run();
result.failure();
const EXPECTED_ERROR_MESSAGE: &str =
"more: '.' is a directory.\nTry 'more --help' for more information.";
assert_eq!(result.stderr_str().trim(), EXPECTED_ERROR_MESSAGE);
} else {}
}

View file

@ -82,7 +82,7 @@ fn test_mv_strip_slashes() {
let dir = "test_mv_strip_slashes_dir";
let file = "test_mv_strip_slashes_file";
let mut source = file.to_owned();
source.push_str("/");
source.push('/');
at.mkdir(dir);
at.touch(file);

View file

@ -9,7 +9,7 @@ use std::io::Write;
use std::path::Path;
// octal dump of 'abcdefghijklmnopqrstuvwxyz\n'
static ALPHA_OUT: &'static str = "
static ALPHA_OUT: &str = "
0000000 061141 062143 063145 064147 065151 066153 067155 070157
0000020 071161 072163 073165 074167 075171 000012
0000033
@ -563,7 +563,7 @@ fn test_dec_offset() {
#[test]
fn test_no_offset() {
let input = [0u8; 31];
const LINE: &'static str = " 00000000 00000000 00000000 00000000\n";
const LINE: &str = " 00000000 00000000 00000000 00000000\n";
let expected_output = [LINE, LINE, LINE, LINE].join("");
new_ucmd!()

View file

@ -7,7 +7,7 @@ struct TestData<'b> {
out: &'b str,
}
static EXAMPLE_DATA: &'static [TestData<'static>] = &[
static EXAMPLE_DATA: &[TestData] = &[
// Ensure that paste properly handles files lacking a final newline.
TestData {
name: "no-nl-1",
@ -64,8 +64,8 @@ static EXAMPLE_DATA: &'static [TestData<'static>] = &[
#[test]
fn test_combine_pairs_of_lines() {
for s in vec!["-s", "--serial"] {
for d in vec!["-d", "--delimiters"] {
for &s in &["-s", "--serial"] {
for &d in &["-d", "--delimiters"] {
new_ucmd!()
.args(&[s, d, "\t\n", "html_colors.txt"])
.run()
@ -76,7 +76,7 @@ fn test_combine_pairs_of_lines() {
#[test]
fn test_multi_stdin() {
for d in vec!["-d", "--delimiters"] {
for &d in &["-d", "--delimiters"] {
new_ucmd!()
.args(&[d, "\t\n", "-", "-"])
.pipe_in_fixture("html_colors.txt")

View file

@ -1,6 +1,6 @@
use crate::common::util::*;
static GIBBERISH: &'static str = "supercalifragilisticexpialidocious";
static GIBBERISH: &str = "supercalifragilisticexpialidocious";
#[test]
fn test_canonicalize() {

View file

@ -61,6 +61,7 @@ const TESTS: [TestCase; 10] = [
},
];
#[allow(clippy::needless_lifetimes)]
fn convert_path<'a>(path: &'a str) -> Cow<'a, str> {
#[cfg(windows)]
return path.replace("/", "\\").into();

View file

@ -14,11 +14,11 @@ fn test_output_is_random_permutation() {
let mut result_seq: Vec<i32> = result
.stdout_str()
.split("\n")
.split('\n')
.filter(|x| !x.is_empty())
.map(|x| x.parse().unwrap())
.collect();
result_seq.sort();
result_seq.sort_unstable();
assert_ne!(result.stdout_str(), input, "Output is not randomised");
assert_eq!(result_seq, input_seq, "Output is not a permutation");
}
@ -31,11 +31,11 @@ fn test_zero_termination() {
let mut result_seq: Vec<i32> = result
.stdout_str()
.split("\0")
.split('\0')
.filter(|x| !x.is_empty())
.map(|x| x.parse().unwrap())
.collect();
result_seq.sort();
result_seq.sort_unstable();
assert_eq!(result_seq, input_seq, "Output is not a permutation");
}
@ -55,11 +55,11 @@ fn test_echo() {
let mut result_seq: Vec<i32> = result
.stdout_str()
.split("\n")
.split('\n')
.filter(|x| !x.is_empty())
.map(|x| x.parse().unwrap())
.collect();
result_seq.sort();
result_seq.sort_unstable();
assert_eq!(result_seq, input_seq, "Output is not a permutation");
}
@ -81,11 +81,11 @@ fn test_head_count() {
let mut result_seq: Vec<i32> = result
.stdout_str()
.split("\n")
.split('\n')
.filter(|x| !x.is_empty())
.map(|x| x.parse().unwrap())
.collect();
result_seq.sort();
result_seq.sort_unstable();
assert_eq!(result_seq.len(), repeat_limit, "Output is not limited");
assert!(
result_seq.iter().all(|x| input_seq.contains(x)),
@ -113,7 +113,7 @@ fn test_repeat() {
let result_seq: Vec<i32> = result
.stdout_str()
.split("\n")
.split('\n')
.filter(|x| !x.is_empty())
.map(|x| x.parse().unwrap())
.collect();
@ -141,11 +141,11 @@ fn test_file_input() {
let mut result_seq: Vec<i32> = result
.stdout_str()
.split("\n")
.split('\n')
.filter(|x| !x.is_empty())
.map(|x| x.parse().unwrap())
.collect();
result_seq.sort();
result_seq.sort_unstable();
assert_eq!(result_seq, expected_seq, "Output is not a permutation");
}

View file

@ -288,7 +288,7 @@ fn test_dictionary_order() {
#[test]
fn test_dictionary_order2() {
for non_dictionary_order2_param in vec!["-d"] {
for non_dictionary_order2_param in &["-d"] {
new_ucmd!()
.pipe_in("a👦🏻aa b\naaaa b")
.arg(non_dictionary_order2_param)
@ -299,7 +299,7 @@ fn test_dictionary_order2() {
#[test]
fn test_non_printing_chars() {
for non_printing_chars_param in vec!["-i"] {
for non_printing_chars_param in &["-i"] {
new_ucmd!()
.pipe_in("a👦🏻aa\naaaa")
.arg(non_printing_chars_param)
@ -361,7 +361,7 @@ fn test_mixed_floats_ints_chars_numeric_stable() {
#[test]
fn test_numeric_floats_and_ints2() {
for numeric_sort_param in vec!["-n", "--numeric-sort"] {
for numeric_sort_param in &["-n", "--numeric-sort"] {
let input = "1.444\n8.013\n1\n-8\n1.04\n-1";
new_ucmd!()
.arg(numeric_sort_param)
@ -373,7 +373,7 @@ fn test_numeric_floats_and_ints2() {
#[test]
fn test_numeric_floats2() {
for numeric_sort_param in vec!["-n", "--numeric-sort"] {
for numeric_sort_param in &["-n", "--numeric-sort"] {
let input = "1.444\n8.013\n1.58590\n-8.90880\n1.040000000\n-.05";
new_ucmd!()
.arg(numeric_sort_param)
@ -426,7 +426,7 @@ fn test_default_unsorted_ints2() {
#[test]
fn test_numeric_unique_ints2() {
for numeric_unique_sort_param in vec!["-nu"] {
for numeric_unique_sort_param in &["-nu"] {
let input = "9\n9\n8\n1\n";
new_ucmd!()
.arg(numeric_unique_sort_param)
@ -471,7 +471,7 @@ fn test_keys_invalid_field() {
new_ucmd!()
.args(&["-k", "1."])
.fails()
.stderr_only("sort: failed to parse character index for key `1.`: cannot parse integer from empty string");
.stderr_only("sort: failed to parse key `1.`: failed to parse character index ``: cannot parse integer from empty string");
}
#[test]
@ -479,7 +479,7 @@ fn test_keys_invalid_field_option() {
new_ucmd!()
.args(&["-k", "1.1x"])
.fails()
.stderr_only("sort: invalid option for key: `x`");
.stderr_only("sort: failed to parse key `1.1x`: invalid option: `x`");
}
#[test]
@ -487,7 +487,7 @@ fn test_keys_invalid_field_zero() {
new_ucmd!()
.args(&["-k", "0.1"])
.fails()
.stderr_only("sort: field index was 0");
.stderr_only("sort: failed to parse key `0.1`: field index can not be 0");
}
#[test]
@ -495,7 +495,7 @@ fn test_keys_invalid_char_zero() {
new_ucmd!()
.args(&["-k", "1.0"])
.fails()
.stderr_only("sort: invalid character index 0 in `1.0` for the start position of a field");
.stderr_only("sort: failed to parse key `1.0`: invalid character index 0 for the start position of a field");
}
#[test]
@ -586,6 +586,47 @@ fn test_keys_negative_size_match() {
test_helper("keys_negative_size", &["-k 3,1"]);
}
#[test]
fn test_keys_ignore_flag() {
test_helper("keys_ignore_flag", &["-k 1n -b"])
}
#[test]
fn test_doesnt_inherit_key_settings() {
let input = " 1
2
10
";
new_ucmd!()
.args(&["-k", "1b", "-n"])
.pipe_in(input)
.succeeds()
.stdout_only(
" 1
10
2
",
);
}
#[test]
fn test_inherits_key_settings() {
let input = " 1
2
10
";
new_ucmd!()
.args(&["-k", "1", "-n"])
.pipe_in(input)
.succeeds()
.stdout_only(
" 1
2
10
",
);
}
#[test]
fn test_zero_terminated() {
test_helper("zero-terminated", &["-z"]);
@ -707,10 +748,9 @@ fn test_dictionary_and_nonprinting_conflicts() {
.succeeds();
}
for conflicting_arg in &conflicting_args {
// FIXME: this should ideally fail.
new_ucmd!()
.args(&["-k", &format!("1{},1{}", restricted_arg, conflicting_arg)])
.succeeds();
.fails();
}
}
}
@ -737,3 +777,8 @@ fn test_nonexistent_file() {
"sort: cannot read: \"nonexistent.txt\": The system cannot find the file specified. (os error 2)",
);
}
#[test]
fn test_blanks() {
test_helper("blanks", &["-b", "--ignore-blanks"]);
}

View file

@ -98,7 +98,7 @@ impl RandomFile {
let to_write = std::cmp::min(remaining_size, buffer.len());
let buf = &mut buffer[..to_write];
rng.fill(buf);
writer.write(buf).unwrap();
writer.write_all(buf).unwrap();
remaining_size -= to_write;
}
@ -179,6 +179,7 @@ fn test_split_bytes_prime_part_size() {
let mut fns = glob.collect();
// glob.collect() is not guaranteed to return in sorted order, so we sort.
fns.sort();
#[allow(clippy::needless_range_loop)]
for i in 0..5 {
assert_eq!(glob.directory.metadata(&fns[i]).len(), 1753);
}
@ -246,9 +247,9 @@ fn test_filter() {
assert!(
glob.collate().iter().find(|&&c| {
// is not i
c != ('i' as u8)
c != (b'i')
// is not newline
&& c != ('\n' as u8)
&& c != (b'\n')
}) == None
);
}
@ -271,7 +272,7 @@ fn test_filter_with_env_var_set() {
let glob = Glob::new(&at, ".", r"x[[:alpha:]][[:alpha:]]$");
assert_eq!(glob.collate(), at.read_bytes(name));
assert!(env::var("FILE").unwrap_or("var was unset".to_owned()) == env_var_value);
assert!(env::var("FILE").unwrap_or_else(|_| "var was unset".to_owned()) == env_var_value);
}
#[test]

View file

@ -97,13 +97,13 @@ fn test_invalid_option() {
}
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
const NORMAL_FMTSTR: &'static str =
const NORMAL_FMTSTR: &str =
"%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s %u %U %x %X %y %Y %z %Z"; // avoid "%w %W" (birth/creation) due to `stat` limitations and linux kernel & rust version capability variations
#[cfg(any(target_os = "linux"))]
const DEV_FMTSTR: &'static str =
const DEV_FMTSTR: &str =
"%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (%t/%T) %u %U %w %W %x %X %y %Y %z %Z";
#[cfg(target_os = "linux")]
const FS_FMTSTR: &'static str = "%b %c %i %l %n %s %S %t %T"; // avoid "%a %d %f" which can cause test failure due to race conditions
const FS_FMTSTR: &str = "%b %c %i %l %n %s %S %t %T"; // avoid "%a %d %f" which can cause test failure due to race conditions
#[test]
#[cfg(target_os = "linux")]
@ -140,7 +140,7 @@ fn test_terse_normal_format() {
assert!(!v_expect.is_empty());
// uu_stat does not support selinux
if v_actual.len() == v_expect.len() - 1 && v_expect[v_expect.len() - 1].contains(":") {
if v_actual.len() == v_expect.len() - 1 && v_expect[v_expect.len() - 1].contains(':') {
// assume last element contains: `SELinux security context string`
v_expect.pop();
}
@ -222,7 +222,7 @@ fn test_symlinks() {
let mut tested: bool = false;
// arbitrarily chosen symlinks with hope that the CI environment provides at least one of them
for file in vec![
for file in &[
"/bin/sh",
"/bin/sudoedit",
"/usr/bin/ex",

View file

@ -5,9 +5,9 @@ use crate::common::util::*;
use std::char::from_digit;
use std::io::Write;
static FOOBAR_TXT: &'static str = "foobar.txt";
static FOOBAR_2_TXT: &'static str = "foobar2.txt";
static FOOBAR_WITH_NULL_TXT: &'static str = "foobar_with_null.txt";
static FOOBAR_TXT: &str = "foobar.txt";
static FOOBAR_2_TXT: &str = "foobar2.txt";
static FOOBAR_WITH_NULL_TXT: &str = "foobar_with_null.txt";
#[test]
fn test_stdin_default() {
@ -153,8 +153,8 @@ fn test_follow_with_pid() {
#[test]
fn test_single_big_args() {
const FILE: &'static str = "single_big_args.txt";
const EXPECTED_FILE: &'static str = "single_big_args_expected.txt";
const FILE: &str = "single_big_args.txt";
const EXPECTED_FILE: &str = "single_big_args_expected.txt";
const LINES: usize = 1_000_000;
const N_ARG: usize = 100_000;
@ -162,13 +162,13 @@ fn test_single_big_args() {
let mut big_input = at.make_file(FILE);
for i in 0..LINES {
write!(&mut big_input, "Line {}\n", i).expect("Could not write to FILE");
writeln!(&mut big_input, "Line {}", i).expect("Could not write to FILE");
}
big_input.flush().expect("Could not flush FILE");
let mut big_expected = at.make_file(EXPECTED_FILE);
for i in (LINES - N_ARG)..LINES {
write!(&mut big_expected, "Line {}\n", i).expect("Could not write to EXPECTED_FILE");
writeln!(&mut big_expected, "Line {}", i).expect("Could not write to EXPECTED_FILE");
}
big_expected.flush().expect("Could not flush EXPECTED_FILE");
@ -201,8 +201,8 @@ fn test_bytes_stdin() {
#[test]
fn test_bytes_big() {
const FILE: &'static str = "test_bytes_big.txt";
const EXPECTED_FILE: &'static str = "test_bytes_big_expected.txt";
const FILE: &str = "test_bytes_big.txt";
const EXPECTED_FILE: &str = "test_bytes_big_expected.txt";
const BYTES: usize = 1_000_000;
const N_ARG: usize = 100_000;
@ -257,10 +257,10 @@ fn test_parse_size() {
for &(c, exp) in &suffixes {
let s = format!("2{}B", c);
assert_eq!(Ok(2 * (1000 as u64).pow(exp)), parse_size(&s));
assert_eq!(Ok(2 * (1000_u64).pow(exp)), parse_size(&s));
let s = format!("2{}", c);
assert_eq!(Ok(2 * (1024 as u64).pow(exp)), parse_size(&s));
assert_eq!(Ok(2 * (1024_u64).pow(exp)), parse_size(&s));
}
// Sizes that are too big.
@ -273,8 +273,8 @@ fn test_parse_size() {
#[test]
fn test_lines_with_size_suffix() {
const FILE: &'static str = "test_lines_with_size_suffix.txt";
const EXPECTED_FILE: &'static str = "test_lines_with_size_suffix_expected.txt";
const FILE: &str = "test_lines_with_size_suffix.txt";
const EXPECTED_FILE: &str = "test_lines_with_size_suffix_expected.txt";
const LINES: usize = 3_000;
const N_ARG: usize = 2 * 1024;

View file

@ -401,8 +401,8 @@ fn get_dstswitch_hour() -> Option<String> {
for _i in 0..(366 * 24) {
if is_dst_switch_hour(ts) {
let mut tm = time::at(ts);
tm.tm_hour = tm.tm_hour + 1;
let s = time::strftime("%Y%m%d%H%M", &tm).unwrap().to_string();
tm.tm_hour += 1;
let s = time::strftime("%Y%m%d%H%M", &tm).unwrap();
return Some(s);
}
ts = ts + time::Duration::hours(1);
@ -415,10 +415,7 @@ fn test_touch_mtime_dst_fails() {
let (_at, mut ucmd) = at_and_ucmd!();
let file = "test_touch_set_mtime_dst_fails";
match get_dstswitch_hour() {
Some(s) => {
ucmd.args(&["-m", "-t", &s, file]).fails();
}
None => (),
if let Some(s) = get_dstswitch_hour() {
ucmd.args(&["-m", "-t", &s, file]).fails();
}
}

View file

@ -1,8 +1,8 @@
use crate::common::util::*;
use std::io::{Seek, SeekFrom, Write};
static TFILE1: &'static str = "truncate_test_1";
static TFILE2: &'static str = "truncate_test_2";
static TFILE1: &str = "truncate_test_1";
static TFILE2: &str = "truncate_test_2";
#[test]
fn test_increase_file_size() {

View file

@ -1,10 +1,10 @@
use crate::common::util::*;
static INPUT: &'static str = "sorted.txt";
static OUTPUT: &'static str = "sorted-output.txt";
static SKIP_CHARS: &'static str = "skip-chars.txt";
static SKIP_FIELDS: &'static str = "skip-fields.txt";
static SORTED_ZERO_TERMINATED: &'static str = "sorted-zero-terminated.txt";
static INPUT: &str = "sorted.txt";
static OUTPUT: &str = "sorted-output.txt";
static SKIP_CHARS: &str = "skip-chars.txt";
static SKIP_FIELDS: &str = "skip-fields.txt";
static SORTED_ZERO_TERMINATED: &str = "sorted-zero-terminated.txt";
#[test]
fn test_stdin_default() {

View file

@ -3,7 +3,7 @@ use crate::common::util::*;
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_count() {
for opt in vec!["-q", "--count"] {
for opt in &["-q", "--count"] {
new_ucmd!()
.arg(opt)
.succeeds()
@ -14,7 +14,7 @@ fn test_count() {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_boot() {
for opt in vec!["-b", "--boot"] {
for opt in &["-b", "--boot"] {
new_ucmd!()
.arg(opt)
.succeeds()
@ -25,7 +25,7 @@ fn test_boot() {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_heading() {
for opt in vec!["-H", "--heading"] {
for opt in &["-H", "--heading"] {
// allow whitespace variation
// * minor whitespace differences occur between platform built-in outputs;
// specifically number of TABs between "TIME" and "COMMENT" may be variant
@ -42,7 +42,7 @@ fn test_heading() {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_short() {
for opt in vec!["-s", "--short"] {
for opt in &["-s", "--short"] {
new_ucmd!()
.arg(opt)
.succeeds()
@ -53,7 +53,7 @@ fn test_short() {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_login() {
for opt in vec!["-l", "--login"] {
for opt in &["-l", "--login"] {
new_ucmd!()
.arg(opt)
.succeeds()
@ -64,7 +64,7 @@ fn test_login() {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_m() {
for opt in vec!["-m"] {
for opt in &["-m"] {
new_ucmd!()
.arg(opt)
.succeeds()
@ -75,7 +75,7 @@ fn test_m() {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_process() {
for opt in vec!["-p", "--process"] {
for opt in &["-p", "--process"] {
new_ucmd!()
.arg(opt)
.succeeds()
@ -85,7 +85,7 @@ fn test_process() {
#[test]
fn test_runlevel() {
for opt in vec!["-r", "--runlevel"] {
for opt in &["-r", "--runlevel"] {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
new_ucmd!()
.arg(opt)
@ -100,7 +100,7 @@ fn test_runlevel() {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_time() {
for opt in vec!["-t", "--time"] {
for opt in &["-t", "--time"] {
new_ucmd!()
.arg(opt)
.succeeds()
@ -117,7 +117,7 @@ fn test_mesg() {
// same as -T
// --writable
// same as -T
for opt in vec!["-T", "-w", "--mesg", "--message", "--writable"] {
for opt in &["-T", "-w", "--mesg", "--message", "--writable"] {
new_ucmd!()
.arg(opt)
.succeeds()
@ -147,7 +147,7 @@ fn test_too_many_args() {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_users() {
for opt in vec!["-u", "--users"] {
for opt in &["-u", "--users"] {
let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str();
let expect = expected_result(&[opt]);
println!("actual: {:?}", actual);
@ -172,18 +172,17 @@ fn test_users() {
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_lookup() {
for opt in vec!["--lookup"] {
new_ucmd!()
.arg(opt)
.succeeds()
.stdout_is(expected_result(&[opt]));
}
let opt = "--lookup";
new_ucmd!()
.arg(opt)
.succeeds()
.stdout_is(expected_result(&[opt]));
}
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test]
fn test_dead() {
for opt in vec!["-d", "--dead"] {
for opt in &["-d", "--dead"] {
new_ucmd!()
.arg(opt)
.succeeds()
@ -222,7 +221,7 @@ fn test_all() {
return;
}
for opt in vec!["-a", "--all"] {
for opt in &["-a", "--all"] {
new_ucmd!()
.arg(opt)
.succeeds()

View file

@ -1,7 +1,4 @@
#![allow(dead_code)]
#[cfg(not(windows))]
use libc;
use pretty_assertions::assert_eq;
use std::env;
#[cfg(not(windows))]
@ -39,7 +36,7 @@ static NO_STDIN_MEANINGLESS: &str = "Setting this flag has no effect if there is
/// Test if the program is running under CI
pub fn is_ci() -> bool {
std::env::var("CI")
.unwrap_or(String::from("false"))
.unwrap_or_else(|_| String::from("false"))
.eq_ignore_ascii_case("true")
}
@ -478,7 +475,7 @@ impl AtPath {
.append(true)
.open(self.plus(name))
.unwrap();
f.write(contents.as_bytes())
f.write_all(contents.as_bytes())
.unwrap_or_else(|e| panic!("Couldn't write {}: {}", name, e));
}
@ -791,7 +788,7 @@ impl UCommand {
if self.has_run {
panic!("{}", ALREADY_RUN);
}
self.comm_string.push_str(" ");
self.comm_string.push(' ');
self.comm_string
.push_str(arg.as_ref().to_str().unwrap_or_default());
self.raw.arg(arg.as_ref());
@ -811,7 +808,7 @@ impl UCommand {
.accept_any();
for s in strings {
self.comm_string.push_str(" ");
self.comm_string.push(' ');
self.comm_string.push_str(&s);
}
@ -867,9 +864,9 @@ impl UCommand {
log_info("run", &self.comm_string);
let mut child = self
.raw
.stdin(self.stdin.take().unwrap_or_else(|| Stdio::piped()))
.stdout(self.stdout.take().unwrap_or_else(|| Stdio::piped()))
.stderr(self.stderr.take().unwrap_or_else(|| Stdio::piped()))
.stdin(self.stdin.take().unwrap_or_else(Stdio::piped))
.stdout(self.stdout.take().unwrap_or_else(Stdio::piped))
.stderr(self.stderr.take().unwrap_or_else(Stdio::piped))
.spawn()
.unwrap();
@ -948,10 +945,7 @@ pub fn read_size(child: &mut Child, size: usize) -> String {
}
pub fn vec_of_size(n: usize) -> Vec<u8> {
let mut result = Vec::new();
for _ in 0..n {
result.push('a' as u8);
}
let result = vec![b'a'; n];
assert_eq!(result.len(), n);
result
}

5
tests/fixtures/sort/blanks.expected vendored Normal file
View file

@ -0,0 +1,5 @@
a
b
x
x
z

View file

@ -0,0 +1,15 @@
a
_
___
b
_
_
x
_
__________
x
_
___
z
_
__

5
tests/fixtures/sort/blanks.txt vendored Normal file
View file

@ -0,0 +1,5 @@
b
a
z
x
x

View file

@ -0,0 +1,2 @@
1a
1A

View file

@ -0,0 +1,6 @@
1a
_
___
1A
_
__

View file

@ -0,0 +1,2 @@
1a
1A