package hu.advancedweb.scott;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.*;

import org.junit.Test;

import hu.advancedweb.scott.helper.TestHelper;

public class RecordMutationTest {
	
	@Test
	public void simpleMutation() throws Exception {
		int i = 5;
		assertThat(TestHelper.getLastRecorderStateFor("i"), equalTo(Integer.toString(i)));
		
		i = 10;
		assertThat(TestHelper.getLastRecorderStateFor("i"), equalTo(Integer.toString(i)));
		
		i = 15;
		assertThat(TestHelper.getLastRecorderStateFor("i"), equalTo(Integer.toString(i)));
	}
	
	@Test
	public void mutateToNull() throws Exception {
		String s = "Hello World!";
		assertThat(TestHelper.getLastRecorderStateFor("s"), equalTo(s));
		
		s = null;
		assertThat(TestHelper.getLastRecorderStateFor("s"), equalTo("null"));
	}
	
	@Test
	public void mutationWithBranches() throws Exception {
		int i = 5;
		assertThat(TestHelper.getLastRecorderStateFor("i"), equalTo(Integer.toString(i)));
		
		if (i < 5) {
			i = 10;
		}
		assertThat(TestHelper.getLastRecorderStateFor("i"), equalTo(Integer.toString(i)));
		
		i = 15;
		assertThat(TestHelper.getLastRecorderStateFor("i"), equalTo(Integer.toString(i)));
	}
	
	@Test
	public void mutationWithBranches_2() throws Exception {
		String outer = "outer";
		assertThat(TestHelper.getLastRecorderStateFor("outer"), equalTo(outer));
		{
			String inner = "inner";
			assertThat(TestHelper.getLastRecorderStateFor("inner"), equalTo(inner));
		}
		
		outer = "outer_changed";
		assertThat(TestHelper.getLastRecorderStateFor("outer"), equalTo(outer));
	}

	@Test
	public void mutationWithLoops() throws Exception {
		int i = 0;
		
		for (int j = 0; j < 10; j++) {
			i = j*2;
			assertThat(TestHelper.getLastRecorderStateFor("i"), equalTo(Integer.toString(i)));
			assertThat(TestHelper.getLastRecorderStateFor("j"), equalTo(Integer.toString(j)));
		}
	}
	
	@Test
	public void objectMutation() throws Exception {
		MyMutable myMutable = new MyMutable(10);
		assertThat(TestHelper.getLastRecorderStateFor("myMutable"), equalTo(myMutable.toString()));
		
		myMutable.set(15);
		assertThat(TestHelper.getLastRecorderStateFor("myMutable"), equalTo(myMutable.toString()));
		
		myMutable.set(20);
		assertThat(TestHelper.getLastRecorderStateFor("myMutable"), equalTo(myMutable.toString()));
	}
	
	@Test
	public void indirectObjectMutation() throws Exception {
		MyMutable myMutable = new MyMutable(10);
		assertThat(TestHelper.getLastRecorderStateFor("myMutable"), equalTo(myMutable.toString()));
		
		MyMutator myMutator = new MyMutator(myMutable);
		myMutator.mutate(15);
		assertThat(TestHelper.getLastRecorderStateFor("myMutable"), equalTo(myMutable.toString()));
	}

	public static class MyMutator {
		MyMutable myMutable;

		MyMutator(MyMutable myMutable) {
			this.myMutable = myMutable;
		}
		
		void mutate(int state) {
			myMutable.set(state);
		}
	}
	
	public static class MyMutable {
		int state;
		
		MyMutable(int state) {
			this.state = state;
		}
		
		void set(int state) {
			this.state = state;
		}

		@Override
		public String toString() {
			return "MyClass [state=" + state + "]";
		}
	}

}

@@ -108,16 +108,41 @@
 ert.*;%0A%0A
+import org.junit.Ignore;%0A
 import o
@@ -156,16 +156,16 @@
 t.Test;%0A
-
 %0Aimport 
@@ -203,16 +203,86 @@
 tHelper;
+%0Aimport hu.advancedweb.scott.runtime.track.LocalVariableStateRegistry;
 %0A%0Apublic
@@ -1673,17 +1673,18 @@
 r));%0A%09%7D%0A
+%09
 %0A
-
 %09@Test%0A%09
@@ -2684,24 +2684,24 @@
 mutate(15);%0A
-
 %09%09assertThat
@@ -2784,16 +2784,206 @@
 ()));%0A%09%7D
+%0A%09%0A%09// FIXME: if i unignore this test, nothing is instrumented%0A%09@Test%0A%09@Ignore%0A%09public void test_4() throws Exception %7B%0A%09%09String b = %22outer%22;%0A%09%09%7B%0A%09%09%09String a = %22inner%22;%0A%09%09%7D%0A%09%09%0A%09%09b = %22Y%22; %0A%09%7D
 %0A%0A%09publi

Add failing test to suite.