use crate::fixtures::{
MAX_FUZZ_INPUT_BYTES,
is_fuzz_input_within_limit,
};
use qubit_json::{
ErrorPrivacyPolicy,
JsonDecodeError,
JsonDecodeErrorKind,
JsonDecodeOptions,
JsonDecodeStage,
JsonTopLevelKind,
LenientJsonDecoder,
};
#[test]
fn test_lib_exports_public_types() {
let decoder = LenientJsonDecoder::default();
let options = JsonDecodeOptions::default();
let kind = JsonTopLevelKind::Other;
let error_kind = JsonDecodeErrorKind::EmptyInput;
let privacy_policy = ErrorPrivacyPolicy::Redacted;
let error: JsonDecodeError = decoder
.decode_value("")
.expect_err("empty input should produce an exported error type");
assert_eq!(decoder.options(), &options);
assert_eq!(kind.to_string(), "other");
assert_eq!(error.kind(), error_kind);
assert_eq!(error.stage(), JsonDecodeStage::Normalize);
assert_eq!(privacy_policy, ErrorPrivacyPolicy::default());
}
#[test]
fn test_ci_workflow_enforces_coverage_thresholds() {
let workflow = include_str!("../.github/workflows/ci.yml");
assert!(workflow.contains("coverage-thresholds:"));
assert!(workflow.contains("needs: rust-ci"));
assert!(workflow.contains("actions/download-artifact@v8"));
assert!(workflow.contains("name: coverage-reports"));
assert!(workflow.contains("functions.percent < 100"));
assert!(workflow.contains("lines.percent <= 95"));
assert!(workflow.contains("regions.percent <= 95"));
}
#[test]
fn test_fuzz_workflow_preserves_decoder_corpus() {
let workflow = include_str!("../.github/workflows/fuzz.yml");
assert!(workflow.contains("timeout-minutes: 15"));
assert!(workflow.contains("actions/cache/restore@v4"));
assert!(workflow.contains("actions/cache/save@v4"));
assert!(workflow.contains("fuzz/corpus/decoder"));
assert!(workflow.contains("github.run_id"));
assert!(workflow.contains("if: always()"));
assert!(workflow.contains("-max_len=4096"));
assert!(workflow.contains("if: failure()"));
assert!(workflow.contains("actions/upload-artifact@v7"));
assert!(workflow.contains("fuzz/artifacts/**"));
}
#[test]
fn test_readme_fuzz_commands_match_workflow_contract() {
let readmes = [
include_str!("../README.md"),
include_str!("../README.zh_CN.md"),
];
for readme in readmes {
assert!(readme.contains(
"rustup toolchain install nightly-2026-06-05 --profile minimal",
));
assert!(
readme
.contains("cargo install cargo-fuzz --version 0.13.2 --locked")
);
assert!(
readme.contains("cargo +nightly-2026-06-05 fuzz build decoder")
);
assert!(readme.contains(
"cargo +nightly-2026-06-05 fuzz run decoder -- -max_len=4096",
));
}
}
#[test]
fn test_decoder_fuzz_input_limit_includes_exact_boundary() {
assert_eq!(MAX_FUZZ_INPUT_BYTES, 4_096);
assert!(is_fuzz_input_within_limit(&vec![0; 4_095]));
assert!(is_fuzz_input_within_limit(&vec![0; 4_096]));
assert!(!is_fuzz_input_within_limit(&vec![0; 4_097]));
}