Compile fixes.
[SquirrelJME.git] / nanocoat / tests / testNvmLocalPopReference.c
blob88d8743f149c68194d050a743ec170da89ca13fd
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include <string.h>
12 #include "mock.h"
13 #include "proto.h"
14 #include "sjme/debug.h"
15 #include "sjme/nvm/nvmFunc.h"
16 #include "test.h"
17 #include "unit.h"
19 #define TEST_NUM_OBJECT_IDS 3
21 typedef struct testHookResult
23 /** The number of GCed objects. */
24 sjme_jint count;
26 /** The GCed objects. */
27 sjme_jobject gc[SJME_MOCK_MAX_OBJECTS];
28 } testHookResult;
30 static sjme_jboolean hookGcNvmLocalPopReference(sjme_nvm_frame frame,
31 sjme_jobject instance)
33 sjme_mock* mock;
34 testHookResult* hookResult;
36 /* Debug. */
37 sjme_message("GC of %p...", instance);
39 /* Mock must be set. */
40 mock = frame->inThread->inState->common.frontEnd.data;
41 if (mock == NULL)
42 return SJME_JNI_FALSE;
44 /* There must be a hook result. */
45 hookResult = mock->special;
46 if (hookResult == NULL)
47 return SJME_JNI_FALSE;
49 /* Track it, within reason. */
50 if (hookResult->count < SJME_MOCK_MAX_OBJECTS)
51 hookResult->gc[hookResult->count++] = instance;
53 /* Success! */
54 return SJME_JNI_TRUE;
57 const sjme_nvm_stateHooks hooksNvmLocalPopReference =
59 .gc = hookGcNvmLocalPopReference,
62 sjme_jboolean configNvmLocalPopReference(
63 sjme_attrInNotNull sjme_mock* inState,
64 sjme_attrInNotNull sjme_mock_configWork* inCurrent)
66 sjme_mock_configDataNvmState* state;
67 sjme_mock_configDataNvmFrame* frame;
69 /* Check. */
70 if (inState == NULL || inCurrent == NULL)
71 return SJME_JNI_FALSE;
73 /* Quick access. */
74 state = &inCurrent->data.nvmState;
75 frame = &inCurrent->data.nvmFrame;
77 /* Configure. */
78 switch (inCurrent->type)
80 case SJME_MOCK_DO_TYPE_NVM_STATE:
81 state->hooks = &hooksNvmLocalPopReference;
82 break;
84 case SJME_MOCK_DO_TYPE_NVM_FRAME:
85 frame->maxLocals = 1;
86 frame->maxStack = 1;
87 frame->treads[SJME_JAVA_TYPE_ID_OBJECT].max = 2;
88 frame->treads[SJME_JAVA_TYPE_ID_OBJECT].stackBaseIndex = 1;
89 break;
92 return SJME_JNI_TRUE;
95 /** Mock set for test. */
96 static const sjme_mock_configSet mockNvmLocalPopReference =
98 configNvmLocalPopReference,
101 /* Mock calls. */
103 sjme_mock_doNvmState,
104 sjme_mock_doNvmThread,
105 sjme_mock_doNvmFrame,
106 sjme_mock_doNvmObject,
107 sjme_mock_doNvmObject,
108 NULL
112 SJME_TEST_DECLARE(testNvmLocalPopReference)
114 sjme_jbyte firstId, secondId;
115 sjme_mock state;
116 sjme_nvm_frame frame;
117 sjme_jint oldNumStack;
118 sjme_nvm_frameTread* objectsTread;
119 sjme_nvm_frameStack* stack;
120 testHookResult hookResult;
122 /* Test all possible combination of objects: [a, b, NULl]. */
123 /* This is for testing that reference counting works in this case. */
124 for (firstId = 0; firstId < TEST_NUM_OBJECT_IDS; firstId++)
125 for (secondId = 0; secondId < TEST_NUM_OBJECT_IDS; secondId++)
127 /* Perform the mock. */
128 memset(&state, 0, sizeof(state));
129 if (!sjme_mock_act(test, &state,
130 &mockNvmLocalPopReference,
131 firstId + (secondId * TEST_NUM_OBJECT_IDS)))
132 sjme_die("Invalid mock");
134 /* Set special data for testing. */
135 memset(&hookResult, 0, sizeof(hookResult));
136 state.special = &hookResult;
138 /* Get initialize frame size. */
139 frame = state.threads[0].nvmThread->top;
141 /* Setup integer values. */
142 objectsTread = frame->treads[SJME_JAVA_TYPE_ID_OBJECT];
143 stack = frame->stack;
144 objectsTread->values.jobjects[0] = state.objects[secondId];
145 objectsTread->values.jobjects[1] = state.objects[firstId];
146 objectsTread->count = objectsTread->stackBaseIndex + 1;
147 stack->count = 1;
148 stack->order[0] = SJME_JAVA_TYPE_ID_OBJECT;
150 /* Pop integer from the stack to the first local. */
151 oldNumStack = stack->count;
152 if (!sjme_nvm_localPopReference(frame, 0))
153 return sjme_unit_fail(test, "Failed to pop local reference.");
155 /* Only a specific object should be GCed and only in a certain */
156 /* circumstance. */
157 if (state.objects[secondId] != NULL &&
158 state.objects[secondId] != state.objects[firstId])
160 sjme_unit_equalL(test,
161 hookResult.gc[0], state.objects[secondId],
162 "Old local was not what should have been GCed?");
163 sjme_unit_equalI(test,
164 hookResult.count, 1,
165 "Different old local not GCed?");
168 /* New stack should be lower. */
169 sjme_unit_equalI(test, stack->count, oldNumStack - 1,
170 "Items in stack not lower?");
172 /* Check that the value was moved over. */
173 sjme_unit_equalL(test, state.objects[firstId],
174 objectsTread->values.jobjects[0],
175 "Popped stack into local was not the correct value.");
177 /* And the stack value was cleared. */
178 sjme_unit_equalL(test, NULL, objectsTread->values.jobjects[1],
179 "Stack value did not get cleared.");
182 /* Success! */
183 return SJME_TEST_RESULT_PASS;