googletest 0.12.0

A rich assertion and matcher library inspired by GoogleTest for C++
Documentation
// 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.

use googletest::matcher::MatcherResult;
use googletest::prelude::*;

#[derive(Debug)]
struct IntField {
    int: i32,
}

#[test]
fn field_matches_integer_field() -> Result<()> {
    verify_that!(IntField { int: 32 }, field!(&IntField.int, eq(32)))
}

#[derive(Debug)]
struct StringField {
    strink: String,
}

#[test]
fn field_matches_string_field() -> Result<()> {
    verify_that!(
        StringField { strink: "yes".to_string() },
        field!(&StringField.strink, ref eq("yes"))
    )
}

#[test]
fn field_error_message_shows_field_name_and_inner_matcher() -> Result<()> {
    let matcher = field!(&IntField.int, eq(31));

    verify_that!(
        matcher.describe(MatcherResult::Match),
        displays_as(eq("has field `int`, which is equal to 31"))
    )
}

mod sub {
    #[derive(Debug)]
    pub struct SubStruct {
        pub field: i32,
    }
}

#[test]
fn struct_in_other_module_matches() -> Result<()> {
    verify_that!(sub::SubStruct { field: 32 }, field!(&sub::SubStruct.field, eq(32)))
}

#[derive(Debug)]
struct Tuple(i32, #[allow(unused)] String);

#[test]
fn tuple_matches_with_index() -> Result<()> {
    verify_that!(Tuple(32, "yes".to_string()), field!(&Tuple.0, eq(32)))
}

#[test]
fn matches_enum_value() -> Result<()> {
    #[derive(Debug)]
    enum AnEnum {
        AValue(u32),
    }
    let value = AnEnum::AValue(123);

    verify_that!(value, field!(&AnEnum::AValue.0, eq(123)))
}

#[test]
fn shows_correct_failure_message_for_wrong_struct_entry() -> Result<()> {
    #[derive(Debug)]
    struct AStruct {
        a: Vec<u32>,
    }
    let value = AStruct { a: vec![1] };

    let result = verify_that!(value, field!(&AStruct.a, ref container_eq([])));

    verify_that!(
        result,
        err(displays_as(contains_substring(
            "which has field `a`, which contains the unexpected element 1"
        )))
    )
}

#[test]
fn does_not_match_enum_value_with_wrong_enum_variant() -> Result<()> {
    #[derive(Debug)]
    enum AnEnum {
        #[allow(dead_code)] // This variant is intentionally unused.
        AValue(u32),
        AnotherValue,
    }
    let value = AnEnum::AnotherValue;

    verify_that!(&value, not(field!(&AnEnum::AValue.0, eq(123))))
}

#[test]
fn shows_correct_failure_message_for_wrong_enum_value() -> Result<()> {
    #[derive(Debug)]
    enum AnEnum {
        #[allow(dead_code)] // This variant is intentionally unused.
        AValue {
            a: u32,
        },
        AnotherValue,
    }
    let value = AnEnum::AnotherValue;

    let result = verify_that!(value, field!(&AnEnum::AValue.a, eq(123)));

    verify_that!(
        result,
        err(displays_as(contains_substring("which has the wrong enum variant `AnotherValue`")))
    )
}

#[test]
fn shows_correct_failure_message_for_wrong_enum_value_with_tuple_field() -> Result<()> {
    #[derive(Debug)]
    enum AnEnum {
        #[allow(dead_code)] // This variant is intentionally unused.
        AValue(u32),
        #[allow(unused)]
        AnotherValue(u32),
    }
    let value = AnEnum::AnotherValue(123);

    let result = verify_that!(value, field!(&AnEnum::AValue.0, eq(123)));

    verify_that!(
        result,
        err(displays_as(contains_substring("which has the wrong enum variant `AnotherValue`")))
    )
}

#[test]
fn shows_correct_failure_message_for_wrong_enum_value_with_named_field() -> Result<()> {
    #[derive(Debug)]
    enum AnEnum {
        #[allow(dead_code)] // This variant is intentionally unused.
        AValue(u32),
        AnotherValue {
            #[allow(unused)]
            a: u32,
        },
    }
    let value = AnEnum::AnotherValue { a: 123 };

    let result = verify_that!(value, field!(&AnEnum::AValue.0, eq(123)));

    verify_that!(
        result,
        err(displays_as(contains_substring("which has the wrong enum variant `AnotherValue`")))
    )
}

#[test]
fn matches_struct_like_enum_value() -> Result<()> {
    #[derive(Debug)]
    enum AnEnum {
        AValue { a_field: u32 },
    }
    let value = AnEnum::AValue { a_field: 123 };

    verify_that!(value, field!(&AnEnum::AValue.a_field, eq(123)))
}

#[test]
fn matches_struct_copy_to_copy() -> Result<()> {
    #[derive(Debug, Clone, Copy)]
    struct Strukt {
        a_field: i32,
    }

    verify_that!(Strukt { a_field: 32 }, field!(Strukt.a_field, eq(32)))
}

#[test]
fn matches_struct_ref_to_copy() -> Result<()> {
    #[derive(Debug)]
    struct Strukt {
        a_field: i32,
    }

    verify_that!(Strukt { a_field: 32 }, field!(&Strukt.a_field, eq(32)))
}

#[test]
fn matches_struct_ref_to_ref() -> Result<()> {
    #[derive(Debug)]
    struct Strukt {
        a_field: String,
    }

    verify_that!(Strukt { a_field: "32".into() }, field!(&Strukt.a_field, ref eq("32")))
}

#[test]
fn matches_struct_copy_to_ref() -> Result<()> {
    // It is not possible to have a copy struct with non-copy field. Hence, this
    // test case is not necessary.
    Ok(())
}

#[test]
fn matches_struct_ref_to_ref_binding_mode() -> Result<()> {
    #[derive(Debug)]
    struct Strukt {
        a_field: String,
    }

    verify_that!(Strukt { a_field: "32".into() }, field!(Strukt.a_field, eq("32")))
}

#[test]
fn matches_struct_with_auto_eq() -> Result<()> {
    #[derive(Debug)]
    struct Strukt {
        a_field: String,
    }

    verify_that!(Strukt { a_field: "32".into() }, field!(Strukt.a_field, "32"))
}

#[test]
fn matches_enum_with_auto_eq() -> Result<()> {
    #[derive(Debug)]
    enum Enum {
        Str(String),
        #[allow(unused)]
        Int(i32),
    }

    verify_that!(Enum::Str("32".into()), field!(Enum::Str.0, "32"))
}

#[test]
fn matches_enum_with_auto_eq_with_wrapper() -> Result<()> {
    #[derive(Debug)]
    struct Wrapper<I> {
        wrapped: I,
    }

    verify_that!(
        Wrapper { wrapped: Wrapper { wrapped: 23 } },
        field!(Wrapper.wrapped, field!(Wrapper.wrapped, &23))
    )
}