summaryrefslogtreecommitdiff
path: root/vendor/windows-implement/src/tests.rs
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/windows-implement/src/tests.rs
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/windows-implement/src/tests.rs')
-rw-r--r--vendor/windows-implement/src/tests.rs135
1 files changed, 135 insertions, 0 deletions
diff --git a/vendor/windows-implement/src/tests.rs b/vendor/windows-implement/src/tests.rs
new file mode 100644
index 00000000..3f5c3493
--- /dev/null
+++ b/vendor/windows-implement/src/tests.rs
@@ -0,0 +1,135 @@
+//! These tests are just a way to quickly run the `#[implement]` macro and see its output.
+//! They don't check the output in any way.
+//!
+//! This exists because of some difficulties of running `cargo expand` against the `#[implement]`
+//! macro. It's also just really convenient. You can see the output by using `--nocapture` and
+//! you'll probably want to restrict the output to a single thread:
+//!
+//! ```text
+//! cargo test -p windows-implement --lib -- --nocapture --test-threads=1
+//! ```
+
+use std::io::{Read, Write};
+use std::process::{Command, Stdio};
+
+use proc_macro2::TokenStream;
+use quote::quote;
+
+fn implement(attributes: TokenStream, item_tokens: TokenStream) -> String {
+ let out_tokens = crate::implement_core(attributes, item_tokens);
+ let tokens_string = out_tokens.to_string();
+
+ let out_string = rustfmt(&tokens_string);
+ println!("// output of #[implement] :");
+ println!();
+ println!("{}", out_string);
+ out_string
+}
+
+fn rustfmt(input: &str) -> String {
+ let mut rustfmt = Command::new("rustfmt");
+
+ rustfmt.stdin(Stdio::piped());
+ rustfmt.stdout(Stdio::piped());
+ rustfmt.stderr(Stdio::inherit());
+
+ let mut child = match rustfmt.spawn() {
+ Ok(c) => c,
+ Err(e) => {
+ eprintln!("failed to spawn rustfmt: {e:?}");
+ return input.to_string();
+ }
+ };
+
+ let mut stdout = child.stdout.take().unwrap();
+
+ // spawn thread to read stdout
+ let stdout_thread = std::thread::spawn(move || {
+ let mut buf = String::new();
+ stdout.read_to_string(&mut buf).unwrap();
+ buf
+ });
+
+ // write unformatted into stdin
+ let mut stdin = child.stdin.take().unwrap();
+ stdin.write_all(input.as_bytes()).unwrap();
+ drop(stdin);
+
+ let stdout_string: String = stdout_thread.join().unwrap();
+
+ let exit = child.wait().unwrap();
+ if !exit.success() {
+ eprintln!("rustfmt terminated with failure status code");
+ return input.to_string();
+ }
+
+ stdout_string
+}
+
+#[test]
+fn simple_type() {
+ implement(
+ quote!(IFoo),
+ quote! {
+ struct Foo {
+ x: u32,
+ }
+ },
+ );
+}
+
+#[test]
+fn zero_sized_type() {
+ implement(
+ quote!(IFoo),
+ quote! {
+ struct Foo;
+ },
+ );
+}
+
+#[test]
+fn no_interfaces() {
+ implement(
+ quote!(),
+ quote! {
+ struct Foo {}
+ },
+ );
+}
+
+#[test]
+fn generic_no_lifetime() {
+ implement(
+ quote!(IAsyncOperationWithProgress<T, P>, IAsyncInfo),
+ quote! {
+ struct OperationWithProgress<T, P>(SyncState<IAsyncOperationWithProgress<T, P>>)
+ where
+ T: RuntimeType + 'static,
+ P: RuntimeType + 'static;
+
+ },
+ );
+}
+
+#[test]
+fn generic_with_lifetime() {
+ implement(
+ quote!(),
+ quote! {
+ pub struct Foo<'a> {
+ pub x: &'a [u8],
+ }
+ },
+ );
+}
+
+#[test]
+fn tuple_type() {
+ implement(
+ quote!(IFoo),
+ quote! {
+ struct Foo(pub i32);
+ },
+ );
+}