@Theory, @DataPoints

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.hasItems;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;

@RunWith(Theories.class)
public class SpaceTest {
	private static final boolean ALIVE = true;
	private static final boolean DEAD = false;

	@DataPoints
	public static Fixture[] DATAS = {
		new Fixture("誕生:死んでいるセルに隣接する生きたセルがちょうど3つならば, 次の世代が誕生する", 
				new Integer[][] {{1,1,0},{1,0,0},{0,0,0}}, ALIVE),
		new Fixture("生存_2:生きているセルに隣接する生きたセルが2つならば, 次の世代でも生存する", 
				new Integer[][] {{1,1,0},{0,1,0},{0,0,0}}, ALIVE),
		new Fixture("生存_3:生きているセルに隣接する生きたセルが3つならば, 次の世代でも生存する", 
				new Integer[][] {{1,1,0},{1,1,0},{0,0,0}}, ALIVE),
		new Fixture("死滅(過疎):生きているセルに隣接する生きたセルが1つ以下ならば, 過疎により死滅する", 
				new Integer[][] {{1,0,0}, {0,1,0}, {0,0,0}}, DEAD),
		new Fixture("死滅(過密):生きているセルに隣接する生きたセルが4つ以上ならば, 過密により死滅する", 
				new Integer[][] {{1,1,1}, {1,1,0}, {0,0,0}}, DEAD)
	};
	
	@Theory
	public void ライフゲームのルールに従ってセルが誕生_生存_死滅すること(Fixture fx) {
		assertThat(fx.description, new Space(fx.init).nextTime().cell(1, 1).isAlive(), 
									is(fx.expected));
	}

	static class Fixture {
		String description;
		Integer[][] init;
		boolean expected;
		public Fixture(String description, Integer[][] init, boolean expected) {
			this.description = description;
			this.init = init;
			this.expected = expected;
		}
	}
}