// 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 // // https://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. //! Various utility functions used in tests. // This file is included directly into integration tests in the // `tests/` directory. These tests are compiled without access to the // rest of the `pdl` crate. To make this work, avoid `use crate::` // statements below. use googletest::prelude::{assert_that, eq}; use std::fs; use std::path::Path; /// Format Rust code in `input`. pub fn format_rust(input: &str) -> String { let syntax_tree = syn::parse_file(input).expect("Could not parse {input:#?} as Rust code"); let formatted = prettyplease::unparse(&syntax_tree); format!("#![rustfmt::skip]\n{formatted}") } /// Compare a string with a snapshot file. /// /// The `snapshot_path` is relative to the current working directory /// of the test binary. This depends on how you execute the tests: /// /// * When using `atest`: The current working directory is a random /// temporary directory. You need to ensure that the snapshot file /// is installed into this directory. You do this by adding the /// snapshot to the `data` attribute of your test rule /// /// * When using Cargo: The current working directory is set to /// `CARGO_MANIFEST_DIR`, which is where the `Cargo.toml` file is /// found. /// /// If you run the test with Cargo and the `UPDATE_SNAPSHOTS` /// environment variable is set, then the `actual_content` will be /// written to `snapshot_path`. Otherwise the content is compared and /// a panic is triggered if they differ. #[track_caller] pub fn assert_snapshot_eq>(snapshot_path: P, actual_content: &str) { let update_snapshots = std::env::var("UPDATE_SNAPSHOTS").is_ok(); let snapshot = snapshot_path.as_ref(); let snapshot_content = match fs::read(snapshot) { Ok(content) => content, Err(_) if update_snapshots => Vec::new(), Err(err) => panic!("Could not read snapshot from {}: {}", snapshot.display(), err), }; let snapshot_content = String::from_utf8(snapshot_content).expect("Snapshot was not UTF-8"); // Normal comparison if UPDATE_SNAPSHOTS is unset. if !update_snapshots { assert_that!(actual_content, eq(&snapshot_content)); } // Bail out if we are not using Cargo. if std::env::var("CARGO_MANIFEST_DIR").is_err() { panic!("Please unset UPDATE_SNAPSHOTS if you are not using Cargo"); } if actual_content != snapshot_content { eprintln!( "Updating snapshot {}: {} -> {} bytes", snapshot.display(), snapshot_content.len(), actual_content.len() ); fs::write(&snapshot_path, actual_content).unwrap_or_else(|err| { panic!("Could not write snapshot to {}: {}", snapshot.display(), err) }); } }