#![allow(clippy::disallowed_names)]

use assert2::assert;

#[test]
fn basic_match() {
	// Test a basic match.
	assert!(let Some(x) = Some(10));
	assert!(x == 10);
}

#[test]
fn basic_match_ref() {
	// Test a basic match on a reference.
	assert!(let Some(x) = &Some(10));
	assert!(x == &10);
}

#[test]
fn basic_match_no_placeholders() {
	assert!(let None = Some(10).filter(|_| false));
	assert!(let None = &Some(10).filter(|_| false));
}

#[test]
fn anonymous_placeholders() {
	// Make sure _ placeholders are ignored.
	assert!(let (_, _, _) = (10, 11, 12));
	assert!(let (x, _, y) = (13, 14, 15));
	assert!(x == 13);
	assert!(y == 15);
}

#[test]
fn underscore_prefixed_placeholders() {
	// But _name placeholders are not ignored.
	assert!(let (_x, _, _y) = (13, 14, 15));
	assert!(_x == 13);
	assert!(_y == 15);
}

#[test]
fn mut_binding() {
	// We should be able to capture things mutably.
	assert!(let mut foo = String::from("foo"));
	foo += " bar";
}

#[test]
fn ref_binding() {
	// We should be able to capture static things by reference.
	assert!(let ref foo = 10);
	std::assert!(foo == &10);
}

#[test]
fn subpattern_binding() {
	// We should be able to capture things that use subpatterns.
	assert!(let foo @ 10 = 10);
	std::assert!(foo == 10);
}

#[test]
fn consume() {
	assert!(let Some(x) = Some(String::from("foo")));
	assert!(x == "foo");
}

#[test]
fn inline_struct() {
	#[derive(Debug, Eq, PartialEq)]
	struct Pet {
		name: String,
		age: u32,
	}
	fn my_pet() -> Pet {
		Pet {
			name: "Xiafeiwu".into(),
			age: 1,
		}
	}
	assert!(my_pet() == Pet {
		name: "Xiafeiwu".into(),
		age: 1,
	});
}

macro_rules! test_panic {
	($name:ident, $($expr:tt)*) => {
		#[test]
		#[should_panic]
		fn $name() {
			$($expr)*;
		}
	}
}

test_panic!(panic_let_assert_err_instead_of_ok, assert!(let Ok(_x) = Result::<i32, i32>::Err(10)));
test_panic!(
	panic_let_assert_err_instead_of_ok_with_message,
	assert!(let Ok(_x) = Result::<i32, i32>::Err(10), "{}", "rust broke")
);
test_panic!(panic_let_assert_no_capture, assert!(let None = Some(10)));
