PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/main/src/mockit/internal/state/ExecutingTest.java

http://jmockit.googlecode.com/
Java | 373 lines | 295 code | 71 blank | 7 comment | 67 complexity | eb2b78351aae73334969b97a4527095c MD5 | raw file
  1. /*
  2. * Copyright (c) 2006-2012 Rog?Šrio Liesenfeld
  3. * This file is subject to the terms of the MIT license (see LICENSE.txt).
  4. */
  5. package mockit.internal.state;
  6. import java.util.*;
  7. import static mockit.internal.util.Utilities.containsReference;
  8. import mockit.external.asm4.*;
  9. import mockit.internal.expectations.*;
  10. import mockit.internal.expectations.invocation.*;
  11. import mockit.internal.expectations.mocking.*;
  12. import mockit.internal.util.*;
  13. @SuppressWarnings("ClassWithTooManyFields")
  14. public final class ExecutingTest
  15. {
  16. private RecordAndReplayExecution currentRecordAndReplay;
  17. private RecordAndReplayExecution recordAndReplayForLastTestMethod;
  18. private boolean shouldIgnoreMockingCallbacks;
  19. private ParameterTypeRedefinitions parameterTypeRedefinitions;
  20. private final Map<MockedType, Object> finalLocalMockFields = new HashMap<MockedType, Object>(4);
  21. private final List<Object> injectableMocks = new ArrayList<Object>();
  22. private final Map<Object, Object> originalToCapturedInstance = new IdentityHashMap<Object, Object>(4);
  23. private final List<Object> nonStrictMocks = new ArrayList<Object>();
  24. private final List<Object> strictMocks = new ArrayList<Object>();
  25. private final Map<String, MockedTypeCascade> cascadingTypes = new HashMap<String, MockedTypeCascade>(4);
  26. public final DefaultResults defaultResults = new DefaultResults();
  27. RecordAndReplayExecution getRecordAndReplay(boolean createIfUndefined)
  28. {
  29. if (currentRecordAndReplay == null && createIfUndefined) {
  30. setRecordAndReplay(new RecordAndReplayExecution());
  31. }
  32. return currentRecordAndReplay;
  33. }
  34. public RecordAndReplayExecution getRecordAndReplay()
  35. {
  36. recordAndReplayForLastTestMethod = null;
  37. RecordAndReplayExecution previous = currentRecordAndReplay;
  38. currentRecordAndReplay = null;
  39. return previous;
  40. }
  41. public void setRecordAndReplay(RecordAndReplayExecution newRecordAndReplay)
  42. {
  43. recordAndReplayForLastTestMethod = null;
  44. currentRecordAndReplay = newRecordAndReplay;
  45. }
  46. public boolean isShouldIgnoreMockingCallbacks() { return shouldIgnoreMockingCallbacks; }
  47. public void setShouldIgnoreMockingCallbacks(boolean flag) { shouldIgnoreMockingCallbacks = flag; }
  48. public void clearRecordAndReplayForVerifications()
  49. {
  50. recordAndReplayForLastTestMethod = null;
  51. }
  52. public RecordAndReplayExecution getRecordAndReplayForVerifications()
  53. {
  54. if (currentRecordAndReplay == null) {
  55. if (recordAndReplayForLastTestMethod != null) {
  56. currentRecordAndReplay = recordAndReplayForLastTestMethod;
  57. }
  58. else {
  59. // This should only happen if no expectations at all were created by the whole test, but
  60. // there is one (probably empty) verification block.
  61. currentRecordAndReplay = new RecordAndReplayExecution();
  62. }
  63. }
  64. return currentRecordAndReplay;
  65. }
  66. public ParameterTypeRedefinitions getParameterTypeRedefinitions() { return parameterTypeRedefinitions; }
  67. public void setParameterTypeRedefinitions(ParameterTypeRedefinitions redefinitions)
  68. { parameterTypeRedefinitions = redefinitions; }
  69. public void clearInjectableAndNonStrictMocks()
  70. {
  71. injectableMocks.clear();
  72. clearNonStrictMocks();
  73. originalToCapturedInstance.clear();
  74. }
  75. public void addInjectableMock(Object mock)
  76. {
  77. if (!isInjectableMock(mock)) {
  78. injectableMocks.add(mock);
  79. }
  80. }
  81. public boolean isInjectableMock(Object mock)
  82. {
  83. for (Object injectableMock : injectableMocks) {
  84. if (mock == injectableMock) {
  85. return true;
  86. }
  87. }
  88. return false;
  89. }
  90. public void addCapturedInstanceForInjectableMock(Object originalInstance, Object capturedInstance)
  91. {
  92. injectableMocks.add(capturedInstance);
  93. addCapturedInstance(originalInstance, capturedInstance);
  94. }
  95. public void addCapturedInstance(Object originalInstance, Object capturedInstance)
  96. {
  97. originalToCapturedInstance.put(capturedInstance, originalInstance);
  98. }
  99. public boolean isInvokedInstanceEquivalentToCapturedInstance(Object invokedInstance, Object capturedInstance)
  100. {
  101. return
  102. invokedInstance == originalToCapturedInstance.get(capturedInstance) ||
  103. capturedInstance == originalToCapturedInstance.get(invokedInstance);
  104. }
  105. public void discardCascadedMockWhenInjectable(Object oldMock)
  106. {
  107. for (int i = 0, n = injectableMocks.size(); i < n; i++) {
  108. if (injectableMocks.get(i) == oldMock) {
  109. injectableMocks.remove(i);
  110. return;
  111. }
  112. }
  113. }
  114. public void addNonStrictMock(Class<?> mockedClass)
  115. {
  116. String mockedClassDesc = Type.getInternalName(mockedClass);
  117. addNonStrictMock(mockedClassDesc.intern());
  118. }
  119. private void addNonStrictMock(Object mock)
  120. {
  121. if (!containsNonStrictMock(mock)) {
  122. nonStrictMocks.add(mock);
  123. }
  124. }
  125. private boolean containsNonStrictMock(Object mockOrClassDesc)
  126. {
  127. return containsReference(nonStrictMocks, mockOrClassDesc);
  128. }
  129. public void addFinalLocalMockField(Object owner, MockedType typeMetadata)
  130. {
  131. finalLocalMockFields.put(typeMetadata, owner);
  132. }
  133. public void addStrictMock(Object mock, String mockClassDesc)
  134. {
  135. addStrictMock(mock);
  136. if (mockClassDesc != null) {
  137. String uniqueMockClassDesc = mockClassDesc.intern();
  138. if (!containsStrictMock(uniqueMockClassDesc) && !containsNonStrictMock(uniqueMockClassDesc)) {
  139. strictMocks.add(uniqueMockClassDesc);
  140. }
  141. }
  142. }
  143. private void addStrictMock(Object mock)
  144. {
  145. if (mock != null && !containsStrictMock(mock)) {
  146. strictMocks.add(mock);
  147. }
  148. }
  149. private boolean containsStrictMock(Object mockOrClassDesc)
  150. {
  151. return containsReference(strictMocks, mockOrClassDesc);
  152. }
  153. public void registerAsNonStrictlyMocked(Class<?> mockedClass)
  154. {
  155. String toBeRegistered = Type.getInternalName(mockedClass).intern();
  156. registerAsNonStrictMock(toBeRegistered, mockedClass);
  157. }
  158. public void registerAsNonStrictlyMocked(Object mockedObject) { registerAsNonStrictMock(mockedObject, mockedObject); }
  159. private void registerAsNonStrictMock(Object toBeRegistered, Object mockedObjectOrClass)
  160. {
  161. if (containsStrictMock(toBeRegistered)) {
  162. throw new IllegalArgumentException("Already mocked strictly: " + mockedObjectOrClass);
  163. }
  164. addNonStrictMock(toBeRegistered);
  165. }
  166. public boolean isNonStrictInvocation(Object mock, String mockClassDesc, String mockNameAndDesc)
  167. {
  168. boolean instanceMethod = isInstanceMethod(mock, mockNameAndDesc);
  169. if (instanceMethod && isOverrideOfObjectMethod(mockNameAndDesc)) {
  170. return true;
  171. }
  172. for (Object nonStrictMock : nonStrictMocks) {
  173. if (nonStrictMock == mock || nonStrictMock == mockClassDesc) {
  174. return true;
  175. }
  176. }
  177. return false;
  178. }
  179. private boolean isInstanceMethod(Object mock, String mockNameAndDesc)
  180. {
  181. return mock != null && mockNameAndDesc.charAt(0) != '<';
  182. }
  183. private boolean isOverrideOfObjectMethod(String mockNameAndDesc)
  184. {
  185. return "equals(Ljava/lang/Object;)Z hashCode()I toString()Ljava/lang/String;".contains(mockNameAndDesc);
  186. }
  187. public void registerAdditionalMocksFromFinalLocalMockFieldsIfAny()
  188. {
  189. if (!finalLocalMockFields.isEmpty()) {
  190. for (
  191. Iterator<Map.Entry<MockedType, Object>> itr = finalLocalMockFields.entrySet().iterator();
  192. itr.hasNext();
  193. ) {
  194. Map.Entry<MockedType, Object> fieldAndOwner = itr.next();
  195. MockedType typeMetadata = fieldAndOwner.getKey();
  196. Object mock = Utilities.getFieldValue(typeMetadata.field, fieldAndOwner.getValue());
  197. // A null field value will occur for invocations executed during initialization of the owner instance.
  198. if (mock != null) {
  199. registerMock(typeMetadata, mock);
  200. itr.remove();
  201. }
  202. }
  203. }
  204. }
  205. public void registerMock(MockedType typeMetadata, Object mock)
  206. {
  207. if (typeMetadata.injectable) {
  208. addInjectableMock(mock);
  209. }
  210. if (typeMetadata.nonStrict) {
  211. addNonStrictMock(mock);
  212. addNonStrictMock(mock.getClass());
  213. }
  214. }
  215. public boolean isStrictInvocation(Object mock, String mockClassDesc, String mockNameAndDesc)
  216. {
  217. if (isInstanceMethod(mock, mockNameAndDesc) && isOverrideOfObjectMethod(mockNameAndDesc)) {
  218. return false;
  219. }
  220. for (Object strictMock : strictMocks) {
  221. if (strictMock == mock) {
  222. return true;
  223. }
  224. else if (strictMock == mockClassDesc) {
  225. addStrictMock(mock);
  226. return true;
  227. }
  228. }
  229. return false;
  230. }
  231. public void clearNonStrictMocks()
  232. {
  233. finalLocalMockFields.clear();
  234. nonStrictMocks.clear();
  235. }
  236. public void addCascadingType(String mockedTypeDesc, boolean mockFieldFromTestClass)
  237. {
  238. if (!cascadingTypes.containsKey(mockedTypeDesc)) {
  239. cascadingTypes.put(mockedTypeDesc, new MockedTypeCascade(mockFieldFromTestClass));
  240. }
  241. }
  242. public MockedTypeCascade getMockedTypeCascade(String mockedTypeDesc, Object mockInstance)
  243. {
  244. if (cascadingTypes.isEmpty()) {
  245. return null;
  246. }
  247. MockedTypeCascade cascade = cascadingTypes.get(mockedTypeDesc);
  248. if (cascade != null || mockInstance == null) {
  249. return cascade;
  250. }
  251. return getMockedTypeCascade(mockedTypeDesc, mockInstance.getClass());
  252. }
  253. private MockedTypeCascade getMockedTypeCascade(String invokedTypeDesc, Class<?> mockedType)
  254. {
  255. Class<?> typeToLookFor = mockedType;
  256. do {
  257. String typeDesc = Type.getInternalName(typeToLookFor);
  258. if (invokedTypeDesc.equals(typeDesc)) {
  259. return null;
  260. }
  261. MockedTypeCascade cascade = cascadingTypes.get(typeDesc);
  262. if (cascade != null) {
  263. return cascade;
  264. }
  265. typeToLookFor = typeToLookFor.getSuperclass();
  266. }
  267. while (typeToLookFor != Object.class);
  268. return null;
  269. }
  270. void finishExecution(boolean clearSharedMocks)
  271. {
  272. recordAndReplayForLastTestMethod = currentRecordAndReplay;
  273. currentRecordAndReplay = null;
  274. if (parameterTypeRedefinitions != null) {
  275. parameterTypeRedefinitions.cleanUp();
  276. parameterTypeRedefinitions = null;
  277. }
  278. if (clearSharedMocks) {
  279. clearNonStrictMocks();
  280. }
  281. strictMocks.clear();
  282. clearNonSharedCascadingTypes();
  283. defaultResults.clear();
  284. }
  285. private void clearNonSharedCascadingTypes()
  286. {
  287. Iterator<MockedTypeCascade> itr = cascadingTypes.values().iterator();
  288. while (itr.hasNext()) {
  289. MockedTypeCascade cascade = itr.next();
  290. if (cascade.mockFieldFromTestClass) {
  291. cascade.discardCascadedMocks();
  292. }
  293. else {
  294. itr.remove();
  295. }
  296. }
  297. }
  298. public void clearCascadingTypes()
  299. {
  300. cascadingTypes.clear();
  301. }
  302. }