use crate::prelude::*;

struct Foo(i32);

impl Default for Foo {
    fn default() -> Self {
        Foo(0)
    }
}

#[session]
impl Foo {
    #[fact]
    fn first_test(self) {
        assert_eq!(0, self.0);
    }

    #[theory]
    #[case(0)]
    fn theory_test(self, i: i32) {
        assert_eq!(i, self.0);
    }
}

// Full example. This must be copied verbatim in the `session` wiki:

use std::fs;
use std::sync::atomic::{AtomicUsize, Ordering};

static FILE_NBR: AtomicUsize = AtomicUsize::new(0);

struct ReadingTest {
    file: String,
}

// Setup the test: create the file that will be read:
impl Default for ReadingTest {
    fn default() -> Self {
        let nbr = FILE_NBR.fetch_add(1, Ordering::SeqCst);
        let file = format!("file_to_read_{}", nbr);

        // Must create a different file for each test to avoid data race:
        fs::write(
            &file,
            "Here is a dummy content for the test: foo, bar, qux.",
        )
        .unwrap();

        ReadingTest { file }
    }
}

// Don't forget to clean up the mess:
impl Drop for ReadingTest {
    fn drop(&mut self) {
        // Try to comment this line: the files will not be cleaned after the tests:
        let _ = fs::remove_file(&self.file);
    }
}

// The tests:
#[session]
impl ReadingTest {
    fn read(&self) -> String {
        let content = fs::read_to_string(&self.file);

        content.as_ref().should().be_ok();
        content.unwrap()
    }

    #[fact]
    fn dummy(self) {
        let content = self.read();

        (&content).should().contain("dummy");
    }

    #[theory]
    #[case("foo")]
    #[case("bar")]
    #[case("qux")]
    fn content(self, word: &str) {
        let content = self.read();

        (&content).should().contain(word);
    }
}
