Migrate some unit tests from ir.rs to ir_from_cc_test using assert_ir_matches

PiperOrigin-RevId: 416796788
diff --git a/rs_bindings_from_cc/ir.rs b/rs_bindings_from_cc/ir.rs
index a0e900c..05a390c 100644
--- a/rs_bindings_from_cc/ir.rs
+++ b/rs_bindings_from_cc/ir.rs
@@ -9,6 +9,7 @@
 use serde::Deserialize;
 use std::collections::HashMap;
 use std::convert::TryFrom;
+use std::fmt;
 use std::io::Read;
 
 pub const TESTING_TARGET: &str = "//test:testing_target";
@@ -116,11 +117,17 @@
     pub cc_type: CcType,
 }
 
-#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
+#[derive(PartialEq, Eq, Hash, Clone, Deserialize)]
 pub struct Identifier {
     pub identifier: String,
 }
 
+impl fmt::Debug for Identifier {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(&format!("\"{}\"", &self.identifier))
+    }
+}
+
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Deserialize)]
 #[serde(transparent)]
 pub struct DeclId(pub usize);
@@ -144,7 +151,7 @@
     }
 }
 
-#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
+#[derive(PartialEq, Eq, Hash, Clone, Deserialize)]
 pub enum UnqualifiedIdentifier {
     Identifier(Identifier),
     Constructor,
@@ -160,6 +167,16 @@
     }
 }
 
+impl fmt::Debug for UnqualifiedIdentifier {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            UnqualifiedIdentifier::Identifier(identifier) => fmt::Debug::fmt(identifier, f),
+            UnqualifiedIdentifier::Constructor => f.write_str("Constructor"),
+            UnqualifiedIdentifier::Destructor => f.write_str("Destructor"),
+        }
+    }
+}
+
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
 pub enum ReferenceQualification {
     LValue,
@@ -453,6 +470,24 @@
     use super::*;
 
     #[test]
+    fn test_identifier_debug_print() {
+        assert_eq!(format!("{:?}", Identifier { identifier: "hello".to_string() }), "\"hello\"");
+    }
+
+    #[test]
+    fn test_unqualified_identifier_debug_print() {
+        assert_eq!(
+            format!(
+                "{:?}",
+                UnqualifiedIdentifier::Identifier(Identifier { identifier: "hello".to_string() })
+            ),
+            "\"hello\""
+        );
+        assert_eq!(format!("{:?}", UnqualifiedIdentifier::Constructor), "Constructor");
+        assert_eq!(format!("{:?}", UnqualifiedIdentifier::Destructor), "Destructor");
+    }
+
+    #[test]
     fn test_used_headers() {
         let input = r#"
         {
@@ -468,265 +503,4 @@
         };
         assert_eq!(ir.flat_ir, expected);
     }
-
-    #[test]
-    fn test_member_access_specifiers() {
-        let input = r#"
-        {
-            "current_target": "//foo:bar",
-            "items": [
-                { "Record" : {
-                    "identifier": {"identifier": "SomeStruct" },
-                    "id": 42,
-                    "owning_target": "//foo:bar",
-                    "fields": [
-                        {
-                            "identifier": {"identifier": "public_int" },
-                            "type": {
-                                "rs_type": {"name": "i32", "lifetime_args": [], "type_args": []},
-                                "cc_type": {"name": "int", "is_const": false, "type_args": []}
-                            },
-                            "access": "Public",
-                            "offset": 0
-                        },
-                        {
-                            "identifier": {"identifier": "protected_int" },
-                            "type": {
-                                "rs_type": {"name": "i32", "lifetime_args": [], "type_args": []},
-                                "cc_type": {"name": "int", "is_const": false, "type_args": []}
-                            },
-                            "access": "Protected",
-                            "offset": 32
-                        },
-                        {
-                            "identifier": {"identifier": "private_int" },
-                            "type": {
-                                "rs_type": {"name": "i32", "lifetime_args": [], "type_args": []},
-                                "cc_type": {"name": "int", "is_const": false, "type_args": []}
-                            },
-                            "access": "Private",
-                            "offset": 64
-                        }
-                    ],
-                    "lifetime_params": [],
-                    "size": 12,
-                    "alignment": 4,
-                    "copy_constructor": {
-                        "definition": "NontrivialUserDefined",
-                        "access": "Private"
-                    },
-                    "move_constructor": {
-                        "definition": "Deleted",
-                        "access": "Protected"
-                    },
-                    "destructor": {
-                        "definition": "Trivial",
-                        "access": "Public"
-                    },
-                    "is_trivial_abi": true
-                }}
-            ]
-        }
-        "#;
-        let ir = deserialize_ir(input.as_bytes()).unwrap();
-        let expected = FlatIR {
-            used_headers: vec![],
-            current_target: "//foo:bar".into(),
-            items: vec![Item::Record(Record {
-                identifier: Identifier { identifier: "SomeStruct".to_string() },
-                id: DeclId(42),
-                owning_target: "//foo:bar".into(),
-                doc_comment: None,
-                fields: vec![
-                    Field {
-                        identifier: Identifier { identifier: "public_int".to_string() },
-                        doc_comment: None,
-                        type_: MappedType {
-                            rs_type: RsType {
-                                name: "i32".to_string().into(),
-                                lifetime_args: vec![],
-                                type_args: vec![],
-                                decl_id: None,
-                            },
-                            cc_type: CcType {
-                                name: "int".to_string().into(),
-                                is_const: false,
-                                type_args: vec![],
-                                decl_id: None,
-                            },
-                        },
-                        access: AccessSpecifier::Public,
-                        offset: 0,
-                    },
-                    Field {
-                        identifier: Identifier { identifier: "protected_int".to_string() },
-                        doc_comment: None,
-                        type_: MappedType {
-                            rs_type: RsType {
-                                name: "i32".to_string().into(),
-                                lifetime_args: vec![],
-                                type_args: vec![],
-                                decl_id: None,
-                            },
-                            cc_type: CcType {
-                                name: "int".to_string().into(),
-                                is_const: false,
-                                type_args: vec![],
-                                decl_id: None,
-                            },
-                        },
-                        access: AccessSpecifier::Protected,
-                        offset: 32,
-                    },
-                    Field {
-                        identifier: Identifier { identifier: "private_int".to_string() },
-                        doc_comment: None,
-                        type_: MappedType {
-                            rs_type: RsType {
-                                name: "i32".to_string().into(),
-                                lifetime_args: vec![],
-                                type_args: vec![],
-                                decl_id: None,
-                            },
-                            cc_type: CcType {
-                                name: "int".to_string().into(),
-                                is_const: false,
-                                type_args: vec![],
-                                decl_id: None,
-                            },
-                        },
-                        access: AccessSpecifier::Private,
-                        offset: 64,
-                    },
-                ],
-                lifetime_params: vec![],
-                size: 12,
-                alignment: 4,
-                copy_constructor: SpecialMemberFunc {
-                    definition: SpecialMemberDefinition::NontrivialUserDefined,
-                    access: AccessSpecifier::Private,
-                },
-                move_constructor: SpecialMemberFunc {
-                    definition: SpecialMemberDefinition::Deleted,
-                    access: AccessSpecifier::Protected,
-                },
-                destructor: SpecialMemberFunc {
-                    definition: SpecialMemberDefinition::Trivial,
-                    access: AccessSpecifier::Public,
-                },
-                is_trivial_abi: true,
-            })],
-        };
-        assert_eq!(ir.flat_ir, expected);
-    }
-
-    #[test]
-    fn test_pointer_member_variable() {
-        let input = r#"
-        {
-            "current_target": "//foo:bar",
-            "items": [
-                { "Record": {
-                    "identifier": {"identifier": "SomeStruct" },
-                    "id": 42,
-                    "owning_target": "//foo:bar",
-                    "fields": [
-                        {
-                            "identifier": {"identifier": "ptr" },
-                            "type": {
-                                "rs_type": {"name": "*mut", "lifetime_args": [], "type_args": [
-                                    {"name": "SomeStruct", "lifetime_args": [], "type_args": [], "decl_id": 42}
-                                ]},
-                                "cc_type": { "name": "*", "is_const": false, "type_args": [
-                                    {
-                                        "name": "SomeStruct",
-                                        "is_const": false,
-                                        "type_args": [],
-                                        "decl_id": 42
-                                    }
-                                ]}
-                            },
-                            "access": "Public",
-                            "offset": 0
-                        }
-                    ],
-                    "lifetime_params": [],
-                    "size": 8,
-                    "alignment": 8,
-                    "copy_constructor": {
-                        "definition": "Trivial",
-                        "access": "Public"
-                    },
-                    "move_constructor": {
-                        "definition": "Trivial",
-                        "access": "Public"
-                    },
-                    "destructor": {
-                        "definition": "Trivial",
-                        "access": "Public"
-                    },
-                    "is_trivial_abi": true
-                }}
-            ]
-        }
-        "#;
-        let ir = deserialize_ir(input.as_bytes()).unwrap();
-        let expected = FlatIR {
-            used_headers: vec![],
-            current_target: "//foo:bar".into(),
-            items: vec![Item::Record(Record {
-                identifier: Identifier { identifier: "SomeStruct".to_string() },
-                id: DeclId(42),
-                owning_target: "//foo:bar".into(),
-                doc_comment: None,
-                fields: vec![Field {
-                    identifier: Identifier { identifier: "ptr".to_string() },
-                    doc_comment: None,
-                    type_: MappedType {
-                        rs_type: RsType {
-                            name: "*mut".to_string().into(),
-                            decl_id: None,
-                            lifetime_args: vec![],
-                            type_args: vec![RsType {
-                                name: "SomeStruct".to_string().into(),
-                                lifetime_args: vec![],
-                                type_args: vec![],
-                                decl_id: Some(DeclId(42)),
-                            }],
-                        },
-                        cc_type: CcType {
-                            name: "*".to_string().into(),
-                            is_const: false,
-                            decl_id: None,
-                            type_args: vec![CcType {
-                                name: "SomeStruct".to_string().into(),
-                                is_const: false,
-                                type_args: vec![],
-                                decl_id: Some(DeclId(42)),
-                            }],
-                        },
-                    },
-                    access: AccessSpecifier::Public,
-                    offset: 0,
-                }],
-                lifetime_params: vec![],
-                size: 8,
-                alignment: 8,
-                move_constructor: SpecialMemberFunc {
-                    definition: SpecialMemberDefinition::Trivial,
-                    access: AccessSpecifier::Public,
-                },
-                copy_constructor: SpecialMemberFunc {
-                    definition: SpecialMemberDefinition::Trivial,
-                    access: AccessSpecifier::Public,
-                },
-                destructor: SpecialMemberFunc {
-                    definition: SpecialMemberDefinition::Trivial,
-                    access: AccessSpecifier::Public,
-                },
-                is_trivial_abi: true,
-            })],
-        };
-        assert_eq!(ir.flat_ir, expected);
-    }
 }
diff --git a/rs_bindings_from_cc/ir_from_cc_test.rs b/rs_bindings_from_cc/ir_from_cc_test.rs
index 1148141..bc22b81 100644
--- a/rs_bindings_from_cc/ir_from_cc_test.rs
+++ b/rs_bindings_from_cc/ir_from_cc_test.rs
@@ -8,8 +8,10 @@
 use ir::*;
 use ir_testing::*;
 use itertools::Itertools;
+use quote::quote;
 use std::collections::HashMap;
 use std::iter::Iterator;
+use token_stream_matchers::{assert_ir_matches, assert_ir_not_matches};
 
 // TODO(mboehme): If we start needing to match on parts of the IR in tests,
 // check out the crate https://crates.io/crates/galvanic-assert.
@@ -69,13 +71,146 @@
 #[test]
 fn test_functions_from_dependency_are_not_emitted() -> Result<()> {
     let ir = ir_from_cc_dependency("int Add(int a, int b);", "int Multiply(int a, int b);")?;
-    let names = ir.functions().map(|i| i.name.identifier_as_str().unwrap()).collect_vec();
-    assert_strings_contain(names.as_slice(), "Add");
-    assert_strings_dont_contain(names.as_slice(), "Multiply");
+    assert_ir_matches!(ir, quote! { Func { name: "Add" ... } });
+    assert_ir_not_matches!(ir, quote! { Func { name: "Multiply" ... } });
     Ok(())
 }
 
 #[test]
+fn test_record_member_variable_access_specifiers() {
+    let ir = ir_from_cc(
+        "
+        struct SomeStruct {
+          public:
+            int public_int;
+          protected:
+            int protected_int;
+          private:
+            int private_int;
+        };
+    ",
+    )
+    .unwrap();
+
+    assert_ir_matches!(
+        ir,
+        quote! {
+            Record {
+                identifier: "SomeStruct" ...
+                fields: [
+                    Field {
+                        identifier: "public_int" ...
+                        access: Public ...
+                    },
+                    Field {
+                        identifier: "protected_int" ...
+                        access: Protected ...
+                    },
+                    Field {
+                        identifier: "private_int" ...
+                        access: Private ...
+                    },
+                ] ...
+            }
+        }
+    );
+}
+
+#[test]
+fn test_record_special_member_access_specifiers() {
+    let ir = ir_from_cc(
+        "
+        struct SomeStruct {
+          private:
+            SomeStruct(SomeStruct& s);
+          protected:
+            SomeStruct(SomeStruct&& s);
+          public:
+            ~SomeStruct();
+        };
+    ",
+    )
+    .unwrap();
+
+    assert_ir_matches!(
+        ir,
+        quote! {
+            Record {
+                identifier: "SomeStruct" ...
+                copy_constructor: SpecialMemberFunc { ... access: Private ... },
+                move_constructor: SpecialMemberFunc { ... access: Protected ... },
+                destructor: SpecialMemberFunc { ... access: Public ... } ...
+            }
+        }
+    );
+}
+
+#[test]
+fn test_record_special_member_definition() {
+    let ir = ir_from_cc(
+        "
+        struct SomeStruct {
+          private:
+            SomeStruct(SomeStruct& s);
+          protected:
+            SomeStruct(SomeStruct&& s) = delete;
+        };
+    ",
+    )
+    .unwrap();
+
+    assert_ir_matches!(
+        ir,
+        quote! {
+            Record {
+                identifier: "SomeStruct" ...
+                copy_constructor: SpecialMemberFunc { definition: NontrivialUserDefined ... },
+                move_constructor: SpecialMemberFunc { definition: Deleted ... },
+                destructor: SpecialMemberFunc { definition: Trivial ... } ...
+            }
+        }
+    );
+}
+
+#[test]
+fn test_pointer_member_variable() {
+    let ir = ir_from_cc(
+        "struct SomeStruct {
+            SomeStruct* ptr;
+        };",
+    )
+    .unwrap();
+    assert_ir_matches!(
+        ir,
+        quote! {
+            Field {
+                identifier: "ptr" ...
+                type_: MappedType {
+                    rs_type: RsType {
+                        name: Some("*mut") ...
+                        type_args: [RsType {
+                            name: None ...
+                            type_args: [],
+                            decl_id: Some(...),
+                        }],
+                        decl_id: None,
+                    },
+                    cc_type: CcType {
+                        name: Some("*") ...
+                        type_args: [CcType {
+                            name: None ...
+                            type_args: [],
+                            decl_id: Some(...),
+                        }],
+                        decl_id: None,
+                    },
+                } ...
+            }
+        }
+    );
+}
+
+#[test]
 fn test_doc_comment() -> Result<()> {
     let ir = ir_from_cc(
         r#"