/* * Copyright (c) 2006-2013 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit.internal.state; import mockit.internal.mockups.*; import mockit.internal.expectations.*; import mockit.internal.expectations.mocking.*; /** * A singleton which stores several data structures which in turn hold global state for individual test methods, test * classes, and for the test run as a whole. */ public final class TestRun { private static final TestRun INSTANCE = new TestRun(); private TestRun() {} // Fields with global state //////////////////////////////////////////////////////////////////////////////////////// private static final ThreadLocal<Integer> noMockingCount = new ThreadLocal<Integer>() { @Override protected Integer initialValue() { return 0; } @Override public void set(Integer valueToAdd) { super.set(get() + valueToAdd); } }; // Used only by the Coverage tool: private int testId; private Class<?> currentTestClass; private Object currentTestInstance; private SavePoint savePointForTestMethod; private SavePoint savePointForTestClass; private SharedFieldTypeRedefinitions sharedFieldTypeRedefinitions; private final MockFixture mockFixture = new MockFixture(); private final ExecutingTest executingTest = new ExecutingTest(); private final MockClasses mockClasses = new MockClasses(); // Static "getters" for global state /////////////////////////////////////////////////////////////////////////////// public static boolean isInsideNoMockingZone() { return noMockingCount.get() > 0; } public static Class<?> getCurrentTestClass() { return INSTANCE.currentTestClass; } public static Object getCurrentTestInstance() { return INSTANCE.currentTestInstance; } @SuppressWarnings("UnusedDeclaration") public static int getTestId() { return INSTANCE.testId; } public static SavePoint getSavePointForTestClass() { return INSTANCE.savePointForTestClass; } public static SharedFieldTypeRedefinitions getSharedFieldTypeRedefinitions() { return INSTANCE.sharedFieldTypeRedefinitions; } public static MockFixture mockFixture() { return INSTANCE.mockFixture; } public static ExecutingTest getExecutingTest() { return INSTANCE.executingTest; } public static RecordAndReplayExecution getRecordAndReplayForRunningTest() { return INSTANCE.currentTestInstance == null ? null : INSTANCE.executingTest.getCurrentRecordAndReplay(); } public static RecordAndReplayExecution getRecordAndReplayForRunningTest(boolean create) { if (INSTANCE.currentTestInstance == null) { return null; } return INSTANCE.executingTest.getRecordAndReplay(INSTANCE.savePointForTestMethod != null && create); } public static MockClasses getMockClasses() { return INSTANCE.mockClasses; } public static void verifyExpectationsOnAnnotatedMocks() { getMockClasses().getMockStates().verifyExpectations(); } // Static "mutators" for global state ////////////////////////////////////////////////////////////////////////////// public static void resetExpectationsOnAnnotatedMocks() { getMockClasses().getMockStates().resetExpectations(); } public static void setCurrentTestClass(Class<?> testClass) { INSTANCE.currentTestClass = testClass; } public static void prepareForNextTest() { INSTANCE.testId++; INSTANCE.executingTest.setRecordAndReplay(null); } public static void setSavePointForTestMethod(SavePoint savePointForTestMethod) { INSTANCE.savePointForTestMethod = savePointForTestMethod; if (savePointForTestMethod != null) { INSTANCE.executingTest.clearRecordAndReplayForVerifications(); } } public static void enterNoMockingZone() { noMockingCount.set(1); } public static void exitNoMockingZone() { noMockingCount.set(-1); } public static void setRunningIndividualTest(Object testInstance) { INSTANCE.currentTestInstance = testInstance; } public static void setSavePointForTestClass(SavePoint savePoint) { INSTANCE.savePointForTestClass = savePoint; } public static void setSharedFieldTypeRedefinitions(SharedFieldTypeRedefinitions redefinitions) { INSTANCE.sharedFieldTypeRedefinitions = redefinitions; } public static void finishCurrentTestExecution(boolean clearSharedMocks) { INSTANCE.savePointForTestMethod = null; INSTANCE.executingTest.finishExecution(clearSharedMocks); } // Methods to be called only from generated bytecode or from the MockingBridge ///////////////////////////////////// public static Object getMock(int index) { return getMockClasses().regularMocks.getMock(index); } @SuppressWarnings("UnusedDeclaration") public static Object getStartupMock(int index) { return getMockClasses().startupMocks.getMock(index); } public static boolean updateMockState(String mockClassDesc, int mockStateIndex) { MockStates mockStates = getMockStates(); return mockStates.updateMockState(mockClassDesc, mockStateIndex); } private static MockStates getMockStates() { return getMockClasses().getMockStates(); } public static void exitReentrantMock(String mockClassDesc, int mockStateIndex) { MockStates mockStates = getMockStates(); mockStates.exitReentrantMock(mockClassDesc, mockStateIndex); } public static MockInvocation createMockInvocation( String mockClassDesc, int mockStateIndex, Object mockedInstance, Object[] mockArgs) { MockStates mockStates = getMockStates(); return mockStates.createMockInvocation(mockClassDesc, mockStateIndex, mockedInstance, mockArgs); } }