mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
Merge branch 'main' into clippy2
This commit is contained in:
commit
b802c8cc3f
8 changed files with 112 additions and 83 deletions
50
.github/workflows/CICD.yml
vendored
50
.github/workflows/CICD.yml
vendored
|
@ -82,56 +82,6 @@ jobs:
|
||||||
grep --ignore-case "all deps seem to have been used" udeps.log || { printf "%s\n" "::${fault_type} ::${fault_prefix}: \`cargo udeps\`: style violation (unused dependency found)" ; fault=true ; }
|
grep --ignore-case "all deps seem to have been used" udeps.log || { printf "%s\n" "::${fault_type} ::${fault_prefix}: \`cargo udeps\`: style violation (unused dependency found)" ; fault=true ; }
|
||||||
if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi
|
if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi
|
||||||
|
|
||||||
fuzz:
|
|
||||||
name: Run the fuzzers
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
RUN_FOR: 60
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
|
||||||
- name: Install `cargo-fuzz`
|
|
||||||
run: cargo install cargo-fuzz
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
|
||||||
- name: Run fuzz_date for XX seconds
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Run it
|
|
||||||
cd fuzz
|
|
||||||
cargo +nightly fuzz run fuzz_date -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
|
||||||
- name: Run fuzz_test for XX seconds
|
|
||||||
continue-on-error: true
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Run it
|
|
||||||
cd fuzz
|
|
||||||
cargo +nightly fuzz run fuzz_test -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
|
||||||
- name: Run fuzz_expr for XX seconds
|
|
||||||
continue-on-error: true
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Run it
|
|
||||||
cd fuzz
|
|
||||||
cargo +nightly fuzz run fuzz_expr -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
|
||||||
- name: Run fuzz_parse_glob for XX seconds
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Run it
|
|
||||||
cd fuzz
|
|
||||||
cargo +nightly fuzz run fuzz_parse_glob -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
|
||||||
- name: Run fuzz_parse_size for XX seconds
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Run it
|
|
||||||
cd fuzz
|
|
||||||
cargo +nightly fuzz run fuzz_parse_size -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
|
||||||
- name: Run fuzz_parse_time for XX seconds
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Run it
|
|
||||||
cd fuzz
|
|
||||||
cargo +nightly fuzz run fuzz_parse_time -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
|
||||||
|
|
||||||
doc_warnings:
|
doc_warnings:
|
||||||
name: Documentation/warnings
|
name: Documentation/warnings
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
|
|
64
.github/workflows/fuzzing.yml
vendored
Normal file
64
.github/workflows/fuzzing.yml
vendored
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
name: Fuzzing
|
||||||
|
|
||||||
|
# spell-checker:ignore fuzzer
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
|
# End the current execution if there is a new changeset in the PR.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
fuzz:
|
||||||
|
name: Run the fuzzers
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
RUN_FOR: 60
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
|
- name: Install `cargo-fuzz`
|
||||||
|
run: cargo install cargo-fuzz
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
- name: Run fuzz_date for XX seconds
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Run it
|
||||||
|
cd fuzz
|
||||||
|
cargo +nightly fuzz run fuzz_date -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
||||||
|
- name: Run fuzz_test for XX seconds
|
||||||
|
continue-on-error: true
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Run it
|
||||||
|
cd fuzz
|
||||||
|
cargo +nightly fuzz run fuzz_test -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
||||||
|
- name: Run fuzz_expr for XX seconds
|
||||||
|
continue-on-error: true
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Run it
|
||||||
|
cd fuzz
|
||||||
|
cargo +nightly fuzz run fuzz_expr -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
||||||
|
- name: Run fuzz_parse_glob for XX seconds
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Run it
|
||||||
|
cd fuzz
|
||||||
|
cargo +nightly fuzz run fuzz_parse_glob -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
||||||
|
- name: Run fuzz_parse_size for XX seconds
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Run it
|
||||||
|
cd fuzz
|
||||||
|
cargo +nightly fuzz run fuzz_parse_size -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
||||||
|
- name: Run fuzz_parse_time for XX seconds
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Run it
|
||||||
|
cd fuzz
|
||||||
|
cargo +nightly fuzz run fuzz_parse_time -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
15
Cargo.lock
generated
15
Cargo.lock
generated
|
@ -783,25 +783,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.1"
|
version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"errno-dragonfly",
|
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "errno-dragonfly"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "exacl"
|
name = "exacl"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
|
|
@ -31,10 +31,12 @@ pub enum AstNode {
|
||||||
operands: OperandsList,
|
operands: OperandsList,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AstNode {
|
impl AstNode {
|
||||||
fn debug_dump(&self) {
|
fn debug_dump(&self) {
|
||||||
self.debug_dump_impl(1);
|
self.debug_dump_impl(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_dump_impl(&self, depth: usize) {
|
fn debug_dump_impl(&self, depth: usize) {
|
||||||
for _ in 0..depth {
|
for _ in 0..depth {
|
||||||
print!("\t",);
|
print!("\t",);
|
||||||
|
@ -52,7 +54,7 @@ impl AstNode {
|
||||||
operands,
|
operands,
|
||||||
} => {
|
} => {
|
||||||
println!(
|
println!(
|
||||||
"Node( {} ) at #{} (evaluate -> {:?})",
|
"Node( {} ) at #{} ( evaluate -> {:?} )",
|
||||||
op_type,
|
op_type,
|
||||||
token_idx,
|
token_idx,
|
||||||
self.evaluate()
|
self.evaluate()
|
||||||
|
@ -71,12 +73,14 @@ impl AstNode {
|
||||||
operands,
|
operands,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_leaf(token_idx: usize, value: &str) -> Box<Self> {
|
fn new_leaf(token_idx: usize, value: &str) -> Box<Self> {
|
||||||
Box::new(Self::Leaf {
|
Box::new(Self::Leaf {
|
||||||
token_idx,
|
token_idx,
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evaluate(&self) -> Result<String, String> {
|
pub fn evaluate(&self) -> Result<String, String> {
|
||||||
match self {
|
match self {
|
||||||
Self::Leaf { value, .. } => Ok(value.clone()),
|
Self::Leaf { value, .. } => Ok(value.clone()),
|
||||||
|
@ -154,9 +158,27 @@ impl AstNode {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn operand_values(&self) -> Result<Vec<String>, String> {
|
pub fn operand_values(&self) -> Result<Vec<String>, String> {
|
||||||
if let Self::Node { operands, .. } = self {
|
if let Self::Node {
|
||||||
|
operands, op_type, ..
|
||||||
|
} = self
|
||||||
|
{
|
||||||
let mut out = Vec::with_capacity(operands.len());
|
let mut out = Vec::with_capacity(operands.len());
|
||||||
|
let mut operands = operands.iter();
|
||||||
|
// check the first value before `|`, stop evaluate and return directly if it is true.
|
||||||
|
// push dummy to pass the check of `len() == 2`
|
||||||
|
if op_type == "|" {
|
||||||
|
if let Some(value) = operands.next() {
|
||||||
|
let value = value.evaluate()?;
|
||||||
|
out.push(value.clone());
|
||||||
|
if value_as_bool(&value) {
|
||||||
|
out.push(String::from("dummy"));
|
||||||
|
return Ok(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for operand in operands {
|
for operand in operands {
|
||||||
let value = operand.evaluate()?;
|
let value = operand.evaluate()?;
|
||||||
out.push(value);
|
out.push(value);
|
||||||
|
@ -240,6 +262,7 @@ fn ast_from_rpn(rpn: &mut TokenStack) -> Result<Box<AstNode>, String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_ast_node(
|
fn maybe_ast_node(
|
||||||
token_idx: usize,
|
token_idx: usize,
|
||||||
op_type: &str,
|
op_type: &str,
|
||||||
|
@ -503,6 +526,7 @@ fn prefix_operator_substr(values: &[String]) -> String {
|
||||||
fn bool_as_int(b: bool) -> u8 {
|
fn bool_as_int(b: bool) -> u8 {
|
||||||
u8::from(b)
|
u8::from(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bool_as_string(b: bool) -> String {
|
fn bool_as_string(b: bool) -> String {
|
||||||
if b {
|
if b {
|
||||||
"1".to_string()
|
"1".to_string()
|
||||||
|
@ -510,6 +534,7 @@ fn bool_as_string(b: bool) -> String {
|
||||||
"0".to_string()
|
"0".to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn value_as_bool(s: &str) -> bool {
|
fn value_as_bool(s: &str) -> bool {
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -38,6 +38,7 @@ pub enum Token {
|
||||||
value: String,
|
value: String,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token {
|
impl Token {
|
||||||
fn new_infix_op(v: &str, left_assoc: bool, precedence: u8) -> Self {
|
fn new_infix_op(v: &str, left_assoc: bool, precedence: u8) -> Self {
|
||||||
Self::InfixOp {
|
Self::InfixOp {
|
||||||
|
@ -46,6 +47,7 @@ impl Token {
|
||||||
value: v.into(),
|
value: v.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_value(v: &str) -> Self {
|
fn new_value(v: &str) -> Self {
|
||||||
Self::Value { value: v.into() }
|
Self::Value { value: v.into() }
|
||||||
}
|
}
|
||||||
|
@ -56,12 +58,14 @@ impl Token {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_a_number(&self) -> bool {
|
fn is_a_number(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Value { value, .. } => value.parse::<BigInt>().is_ok(),
|
Self::Value { value, .. } => value.parse::<BigInt>().is_ok(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_a_close_paren(&self) -> bool {
|
fn is_a_close_paren(&self) -> bool {
|
||||||
matches!(*self, Self::ParClose)
|
matches!(*self, Self::ParClose)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,23 +17,6 @@ pub enum FieldType {
|
||||||
Charf,
|
Charf,
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[allow(non_camel_case_types)]
|
|
||||||
// pub enum FChar {
|
|
||||||
// d,
|
|
||||||
// e,
|
|
||||||
// E,
|
|
||||||
// i,
|
|
||||||
// f,
|
|
||||||
// F,
|
|
||||||
// g,
|
|
||||||
// G,
|
|
||||||
// u,
|
|
||||||
// x,
|
|
||||||
// X,
|
|
||||||
// o
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
// a Sub Tokens' fields are stored
|
// a Sub Tokens' fields are stored
|
||||||
// as a single object so they can be more simply
|
// as a single object so they can be more simply
|
||||||
// passed by ref to num_format in a Sub method
|
// passed by ref to num_format in a Sub method
|
||||||
|
|
|
@ -18,7 +18,6 @@ use std::iter::Peekable;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::slice::Iter;
|
use std::slice::Iter;
|
||||||
use std::str::Chars;
|
use std::str::Chars;
|
||||||
// use std::collections::HashSet;
|
|
||||||
|
|
||||||
use super::num_format::format_field::{FieldType, FormatField};
|
use super::num_format::format_field::{FieldType, FormatField};
|
||||||
use super::num_format::num_format;
|
use super::num_format::num_format;
|
||||||
|
|
|
@ -123,6 +123,21 @@ fn test_or() {
|
||||||
.args(&["-14", "|", "1"])
|
.args(&["-14", "|", "1"])
|
||||||
.succeeds()
|
.succeeds()
|
||||||
.stdout_only("-14\n");
|
.stdout_only("-14\n");
|
||||||
|
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["1", "|", "a", "/", "5"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only("1\n");
|
||||||
|
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["foo", "|", "a", "/", "5"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only("foo\n");
|
||||||
|
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["0", "|", "10", "/", "5"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only("2\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue