1   /*
2    * Copyright (C) 2012 Atlassian
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.atlassian.jira.rest.client.functest.framework;
17  
18  import com.atlassian.jira.functest.framework.Administration;
19  import com.atlassian.jira.functest.framework.Form;
20  import com.atlassian.jira.functest.framework.FuncTestCase;
21  import com.atlassian.jira.functest.framework.HtmlPage;
22  import com.atlassian.jira.functest.framework.LocatorFactory;
23  import com.atlassian.jira.functest.framework.Navigation;
24  import com.atlassian.jira.functest.framework.Parser;
25  import com.atlassian.jira.functest.framework.assertions.Assertions;
26  import com.atlassian.jira.functest.framework.assertions.TextAssertions;
27  import com.atlassian.jira.functest.framework.log.FuncTestLogger;
28  import com.atlassian.jira.rest.client.annotation.Annotations;
29  import com.atlassian.jira.rest.client.annotation.Restore;
30  import com.atlassian.jira.rest.client.annotation.RestoreOnce;
31  import com.atlassian.jira.webtests.util.JIRAEnvironmentData;
32  import com.google.common.base.Objects;
33  import com.google.common.base.Strings;
34  import net.sourceforge.jwebunit.WebTester;
35  import org.junit.After;
36  import org.junit.Before;
37  import org.junit.BeforeClass;
38  import org.junit.Rule;
39  import org.junit.rules.TestName;
40  
41  import java.lang.reflect.Method;
42  
43  public class FuncTestCase4 {
44  
45  	private static boolean wasRestorePerformed;
46  
47  	@Rule
48  	public TestName runningTestMethod = new TestName();
49  
50  	// From FuncTestCase {
51  	public WebTester tester;
52  	public Navigation navigation;
53  	public Form form;
54  	public HtmlPage page;
55  	public Administration administration;
56  	public Assertions assertions;
57  	public TextAssertions text;
58  	public Parser parse;
59  	public FuncTestLogger log;
60  	public LocatorFactory locator;
61  	public JIRAEnvironmentData environmentData;
62  	// }
63  
64  	private FakeFuncTestCase fakeFuncTestCase;
65  
66  	@BeforeClass
67  	public static void beforeClass() {
68  		wasRestorePerformed = false;
69  	}
70  
71  	@Before
72  	public void beforeMethod() {
73  		fakeFuncTestCase = new FakeFuncTestCase();
74  		fakeFuncTestCase.setMeUp();
75  
76  		doRestore();
77  	}
78  
79  	@After
80  	public void afterMethod() {
81  		fakeFuncTestCase.cleanUp();
82  	}
83  
84  	protected RestoreConfig getRestoreConfig() {
85  		return getRestoreConfigFromAnnotations();
86  	}
87  
88  	private void doRestore() {
89  		final RestoreConfig rc = getRestoreConfig();
90  		if (rc.restoreMode == RestoreConfig.RestoreMode.RESTORE_ALWAYS ||
91  				(rc.restoreMode == RestoreConfig.RestoreMode.RESTORE_ONCE && !wasRestorePerformed)) {
92  
93  			administration.restoreData(rc.restoreFile);
94  			wasRestorePerformed = true;
95  		}
96  	}
97  
98  	private RestoreConfig getRestoreConfigFromAnnotations() {
99  		// First check if there is @Restore on method
100 		final Class<? extends FuncTestCase4> aClass = this.getClass();
101 		if (!Strings.isNullOrEmpty(runningTestMethod.getMethodName())) {
102 			try {
103 				final Method m = aClass.getMethod(runningTestMethod.getMethodName());
104 				final Restore restore = m.getAnnotation(Restore.class);
105 				if (restore != null) {
106 					return RestoreConfig.restoreAlways(restore.value());
107 				}
108 			} catch (NoSuchMethodException e) {
109 				// method with params? not supported for now, ignore
110 			}
111 		}
112 
113 		// Check for @RestoreOnce and @Restore on class (and super classes)
114 		final RestoreOnce restoreOnce = Annotations.getAnnotationIncludingParents(aClass, RestoreOnce.class);
115 		final Restore restore = Annotations.getAnnotationIncludingParents(aClass, Restore.class);
116 		if (restore != null) {
117 			if (restoreOnce != null) {
118 				throw new RuntimeException("Both @Restore and @RestoreOnce found on class. Only one should be present.");
119 			}
120 
121 			return RestoreConfig.restoreAlways(restore.value());
122 		} else if (restoreOnce != null) {
123 			return RestoreConfig.restoreOnce(restoreOnce.value());
124 		} else {
125 			return RestoreConfig.doNotRestore();
126 		}
127 	}
128 
129 	public static class RestoreConfig {
130 
131 		public static RestoreConfig doNotRestore() {
132 			return new RestoreConfig(null, RestoreMode.DO_NOT_RESTORE);
133 		}
134 
135 		public static RestoreConfig restoreOnce(final String restoreFile) {
136 			return new RestoreConfig(restoreFile, RestoreMode.RESTORE_ONCE);
137 		}
138 
139 		public static RestoreConfig restoreAlways(final String restoreFile) {
140 			return new RestoreConfig(restoreFile, RestoreMode.RESTORE_ALWAYS);
141 		}
142 
143 		public RestoreConfig(final String restoreFile, final RestoreMode restoreMode) {
144 			this.restoreFile = restoreFile;
145 			this.restoreMode = restoreMode;
146 		}
147 
148 		public static enum RestoreMode {
149 			RESTORE_ALWAYS,
150 			RESTORE_ONCE,
151 			DO_NOT_RESTORE
152 		}
153 
154 		private final RestoreMode restoreMode;
155 		private final String restoreFile;
156 
157 		@Override
158 		public String toString() {
159 			return Objects.toStringHelper(this).
160 					add("restoreMode", restoreMode).
161 					add("restoreFile", restoreFile).
162 					toString();
163 		}
164 	}
165 
166 	public class FakeFuncTestCase extends FuncTestCase {
167 
168 		public void setMeUp() {
169 			setUp();
170 
171 			final FuncTestCase4 ftc = FuncTestCase4.this;
172 			ftc.environmentData = funcTestHelperFactory.getEnvironmentData();
173 			ftc.tester = this.tester;
174 			ftc.navigation = this.navigation;
175 			ftc.form = this.form;
176 			ftc.page = this.page;
177 			ftc.administration = this.administration;
178 			ftc.assertions = this.assertions;
179 			ftc.text = this.text;
180 			ftc.parse = this.parse;
181 			ftc.log = this.log;
182 			ftc.locator = this.locator;
183 		}
184 
185 		public void cleanUp() {
186 			try {
187 				final Method clearTestCaseVariablesMethod = FuncTestCase.class.getDeclaredMethod("clearTestCaseVariables");
188 				clearTestCaseVariablesMethod.setAccessible(true);
189 				clearTestCaseVariablesMethod.invoke(this);
190 			} catch (Exception e) {
191 				throw new RuntimeException(e);
192 			}
193 		}
194 	}
195 
196 }