| // Copyright 2023 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| extern crate core; |
| |
| use clap::Parser as _; |
| use cmd_runner::run_cmd_shell; |
| use env_logger::Env; |
| use std::{env, path}; |
| |
| mod crypto_ffi; |
| mod ffi; |
| mod fuzzers; |
| mod jni; |
| mod license; |
| mod ukey2; |
| |
| fn main() -> anyhow::Result<()> { |
| env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); |
| let cli: Cli = Cli::parse(); |
| |
| let root_dir = path::PathBuf::from( |
| env::var("CARGO_MANIFEST_DIR").expect("Must be run via Cargo to establish root directory"), |
| ); |
| |
| match cli.subcommand { |
| Subcommand::CheckEverything { ref check_options } => { |
| check_everything(&root_dir, check_options)? |
| } |
| Subcommand::CheckWorkspace(ref options) => check_workspace(&root_dir, options)?, |
| Subcommand::FfiCheckEverything(ref options) => ffi::check_everything(&root_dir, options)?, |
| Subcommand::BoringsslCheckEverything(ref options) => { |
| crypto_ffi::boringssl_check_everything(&root_dir, options)? |
| } |
| Subcommand::BuildBoringssl => crypto_ffi::build_boringssl(&root_dir)?, |
| Subcommand::CheckBoringssl(ref options) => crypto_ffi::check_boringssl(&root_dir, options)?, |
| Subcommand::PrepareRustOpenssl => crypto_ffi::prepare_patched_rust_openssl(&root_dir)?, |
| Subcommand::CheckOpenssl(ref options) => crypto_ffi::check_openssl(&root_dir, options)?, |
| Subcommand::RunRustFuzzers => fuzzers::run_rust_fuzzers(&root_dir)?, |
| Subcommand::BuildFfiFuzzers => fuzzers::build_ffi_fuzzers(&root_dir)?, |
| Subcommand::CheckLicenseHeaders => license::check_license_headers(&root_dir)?, |
| Subcommand::AddLicenseHeaders => license::add_license_headers(&root_dir)?, |
| Subcommand::CheckLdtFfi => ffi::check_ldt_ffi_rust(&root_dir)?, |
| Subcommand::CheckUkey2Ffi(ref options) => ukey2::check_ukey2_ffi(&root_dir, options)?, |
| Subcommand::CheckLdtJni => jni::check_ldt_jni(&root_dir)?, |
| Subcommand::CheckNpFfi(ref options) => ffi::check_np_ffi_rust(&root_dir, options)?, |
| Subcommand::CheckLdtCmake(ref options) => ffi::check_ldt_cmake(&root_dir, options)?, |
| Subcommand::CheckNpFfiCmake(ref options) => ffi::check_np_ffi_cmake(&root_dir, options)?, |
| Subcommand::RunKotlinTests => jni::run_kotlin_tests(&root_dir)?, |
| } |
| |
| Ok(()) |
| } |
| |
| pub fn check_workspace(root: &path::Path, options: &CheckOptions) -> anyhow::Result<()> { |
| log::info!("Running cargo checks on workspace"); |
| |
| let fmt_command = if options.reformat { "cargo fmt" } else { "cargo fmt --check" }; |
| |
| for cargo_cmd in [ |
| // ensure formatting is correct (Check for it first because it is fast compared to running tests) |
| fmt_command, |
| // make sure everything compiles |
| "cargo check --workspace --all-targets --quiet", |
| // run all the tests |
| //TODO: re-enable the openssl tests, this was potentially failing due to UB code in the |
| // upstream rust-openssl crate's handling of empty slices. This repros consistently when |
| // using the rust-openssl crate backed by openssl-sys on Ubuntu 20.04. |
| "cargo test --workspace --quiet --exclude crypto_provider_openssl -- --color=always", |
| // Test ukey2 builds with different crypto providers |
| "cargo test -p ukey2_connections -p ukey2_rs --no-default-features --features test_rustcrypto", |
| "cargo test -p ukey2_connections -p ukey2_rs --no-default-features --features test_openssl", |
| // ensure the docs are valid (cross-references to other code, etc) |
| concat!( |
| "RUSTDOCFLAGS='--deny warnings -Z unstable-options --enable-index-page --generate-link-to-definition' ", |
| "cargo +nightly doc --quiet --workspace --no-deps --document-private-items ", |
| "--target-dir target/dist_docs", |
| ), |
| "cargo clippy --all-targets --workspace -- --deny warnings", |
| "cargo deny --workspace check", |
| ] { |
| run_cmd_shell(root, cargo_cmd)?; |
| } |
| |
| Ok(()) |
| } |
| pub fn check_everything(root: &path::Path, check_options: &CheckOptions) -> anyhow::Result<()> { |
| license::check_license_headers(root)?; |
| check_workspace(root, check_options)?; |
| crypto_ffi::check_boringssl(root, &check_options.cargo_options)?; |
| crypto_ffi::check_openssl(root, &check_options.cargo_options)?; |
| ffi::check_everything(root, &check_options.cargo_options)?; |
| jni::check_ldt_jni(root)?; |
| jni::run_kotlin_tests(root)?; |
| ukey2::check_ukey2_ffi(root, &check_options.cargo_options)?; |
| fuzzers::run_rust_fuzzers(root)?; |
| fuzzers::build_ffi_fuzzers(root)?; |
| |
| Ok(()) |
| } |
| |
| #[derive(clap::Parser)] |
| struct Cli { |
| #[clap(subcommand)] |
| subcommand: Subcommand, |
| } |
| |
| #[derive(clap::Subcommand, Debug, Clone)] |
| enum Subcommand { |
| /// Checks everything in beto-rust |
| CheckEverything { |
| #[command(flatten)] |
| check_options: CheckOptions, |
| }, |
| /// Checks everything included in the top level workspace |
| CheckWorkspace(CheckOptions), |
| /// Checks everything related to the boringssl version (equivalent of running check-boringssl |
| /// + check-openssl) |
| BoringsslCheckEverything(CargoOptions), |
| /// Clones boringssl and uses bindgen to generate the rust crate |
| BuildBoringssl, |
| /// Run crypto provider tests using boringssl backend |
| CheckBoringssl(CargoOptions), |
| /// Applies AOSP specific patches to the 3p `openssl` crate so that it can use a boringssl |
| /// backend |
| PrepareRustOpenssl, |
| /// Run crypto provider tests using openssl crate with boringssl backend |
| CheckOpenssl(CargoOptions), |
| /// Build and run pure Rust fuzzers for 10000 runs |
| RunRustFuzzers, |
| /// Build FFI fuzzers |
| BuildFfiFuzzers, |
| /// Builds and runs tests for all C/C++ projects. This is a combination of CheckNpFfi, |
| /// CheckLdtFfi, and CheckCmakeBuildAndTests |
| FfiCheckEverything(CargoOptions), |
| /// Builds the crate checks the cbindgen generation of C/C++ bindings |
| CheckNpFfi(CargoOptions), |
| /// Builds ldt_np_adv_ffi crate with all possible different sets of feature flags |
| CheckLdtFfi, |
| /// Checks the CMake build and runs all of the C/C++ tests |
| CheckLdtCmake(CargoOptions), |
| /// Checks the CMake build and runs all of the C/C++ tests |
| CheckNpFfiCmake(CargoOptions), |
| /// Checks the workspace 3rd party crates and makes sure they have a valid license |
| CheckLicenseHeaders, |
| /// Generate new headers for any files that are missing them |
| AddLicenseHeaders, |
| /// Builds and runs tests for the UKEY2 FFI |
| CheckUkey2Ffi(CargoOptions), |
| /// Checks the build of ldt_jni wrapper with non default features, ie rust-openssl, and boringssl |
| CheckLdtJni, |
| /// Runs the kotlin tests of the LDT Jni API |
| RunKotlinTests, |
| } |
| |
| #[derive(clap::Args, Debug, Clone, Default)] |
| pub struct CheckOptions { |
| #[arg(long, help = "reformat files with cargo fmt")] |
| reformat: bool, |
| #[command(flatten)] |
| cargo_options: CargoOptions, |
| } |
| |
| #[derive(clap::Args, Debug, Clone, Default)] |
| pub struct CargoOptions { |
| #[arg(long, help = "whether to run cargo with --locked")] |
| locked: bool, |
| } |