1 #include "errno.h"
2 #include "string.h"
3 
4 #include "jsctypes-test.h"
5 #include "jsctypes-test-finalizer.h"
6 
7 /**
8  * Shared infrastructure
9  */
10 
11 /**
12  * An array of integers representing resources.
13  * - 0: unacquired
14  * - 1: acquired
15  * - < 0: error, resource has been released several times.
16  */
17 int* gFinalizerTestResources = nullptr;
18 char** gFinalizerTestNames = nullptr;
19 size_t gFinalizerTestSize;
20 
test_finalizer_start(size_t size)21 void test_finalizer_start(size_t size) {
22   gFinalizerTestResources = new int[size];
23   gFinalizerTestNames = new char*[size];
24   gFinalizerTestSize = size;
25   for (size_t i = 0; i < size; ++i) {
26     gFinalizerTestResources[i] = 0;
27     gFinalizerTestNames[i] = nullptr;
28   }
29 }
30 
test_finalizer_stop()31 void test_finalizer_stop() { delete[] gFinalizerTestResources; }
32 
33 /**
34  * Check if an acquired resource has been released
35  */
test_finalizer_resource_is_acquired(size_t i)36 bool test_finalizer_resource_is_acquired(size_t i) {
37   return gFinalizerTestResources[i] == 1;
38 }
39 // Resource type: size_t
40 
41 // Acquire resource i
test_finalizer_acq_size_t(size_t i)42 size_t test_finalizer_acq_size_t(size_t i) {
43   gFinalizerTestResources[i] = 1;
44   return i;
45 }
46 
47 // Release resource i
test_finalizer_rel_size_t(size_t i)48 void test_finalizer_rel_size_t(size_t i) {
49   if (--gFinalizerTestResources[i] < 0) {
50     MOZ_CRASH("Assertion failed");
51   }
52 }
53 
test_finalizer_rel_size_t_return_size_t(size_t i)54 size_t test_finalizer_rel_size_t_return_size_t(size_t i) {
55   if (--gFinalizerTestResources[i] < 0) {
56     MOZ_CRASH("Assertion failed");
57   }
58   return i;
59 }
60 
test_finalizer_rel_size_t_return_struct_t(size_t i)61 myRECT test_finalizer_rel_size_t_return_struct_t(size_t i) {
62   if (--gFinalizerTestResources[i] < 0) {
63     MOZ_CRASH("Assertion failed");
64   }
65   const int32_t narrowed = (int32_t)i;
66   myRECT result = {narrowed, narrowed, narrowed, narrowed};
67   return result;
68 }
69 
test_finalizer_cmp_size_t(size_t a,size_t b)70 bool test_finalizer_cmp_size_t(size_t a, size_t b) { return a == b; }
71 
72 // Resource type: int32_t
73 
74 // Acquire resource i
test_finalizer_acq_int32_t(size_t i)75 int32_t test_finalizer_acq_int32_t(size_t i) {
76   gFinalizerTestResources[i] = 1;
77   return i;
78 }
79 
80 // Release resource i
test_finalizer_rel_int32_t(int32_t i)81 void test_finalizer_rel_int32_t(int32_t i) {
82   if (--gFinalizerTestResources[i] < 0) {
83     MOZ_CRASH("Assertion failed");
84   }
85 }
86 
test_finalizer_cmp_int32_t(int32_t a,int32_t b)87 bool test_finalizer_cmp_int32_t(int32_t a, int32_t b) { return a == b; }
88 
89 // Resource type: int64_t
90 
91 // Acquire resource i
test_finalizer_acq_int64_t(size_t i)92 int64_t test_finalizer_acq_int64_t(size_t i) {
93   gFinalizerTestResources[i] = 1;
94   return i;
95 }
96 
97 // Release resource i
test_finalizer_rel_int64_t(int64_t i)98 void test_finalizer_rel_int64_t(int64_t i) {
99   if (--gFinalizerTestResources[i] < 0) {
100     MOZ_CRASH("Assertion failed");
101   }
102 }
103 
test_finalizer_cmp_int64_t(int64_t a,int64_t b)104 bool test_finalizer_cmp_int64_t(int64_t a, int64_t b) { return a == b; }
105 
106 // Resource type: void*
107 
108 // Acquire resource i
test_finalizer_acq_ptr_t(size_t i)109 void* test_finalizer_acq_ptr_t(size_t i) {
110   gFinalizerTestResources[i] = 1;
111   return (void*)&gFinalizerTestResources[i];
112 }
113 
114 // Release resource i
test_finalizer_rel_ptr_t(void * i)115 void test_finalizer_rel_ptr_t(void* i) {
116   int* as_int = (int*)i;
117   --(*as_int);
118   if (*as_int < 0) {
119     MOZ_CRASH("Assertion failed");
120   }
121 }
122 
test_finalizer_cmp_ptr_t(void * a,void * b)123 bool test_finalizer_cmp_ptr_t(void* a, void* b) { return a == b; }
124 
125 // Resource type: int32_t*
126 
127 // Acquire resource i
test_finalizer_acq_int32_ptr_t(size_t i)128 int32_t* test_finalizer_acq_int32_ptr_t(size_t i) {
129   gFinalizerTestResources[i] = 1;
130   return (int32_t*)&gFinalizerTestResources[i];
131 }
132 
133 // Release resource i
test_finalizer_rel_int32_ptr_t(int32_t * i)134 void test_finalizer_rel_int32_ptr_t(int32_t* i) {
135   --(*i);
136   if (*i < 0) {
137     MOZ_CRASH("Assertion failed");
138   }
139 }
140 
test_finalizer_cmp_int32_ptr_t(int32_t * a,int32_t * b)141 bool test_finalizer_cmp_int32_ptr_t(int32_t* a, int32_t* b) { return a == b; }
142 
143 // Resource type: nullptr
144 
145 // Acquire resource i
test_finalizer_acq_null_t(size_t i)146 void* test_finalizer_acq_null_t(size_t i) {
147   gFinalizerTestResources[0] = 1;  // Always index 0
148   return nullptr;
149 }
150 
151 // Release resource i
test_finalizer_rel_null_t(void * i)152 void test_finalizer_rel_null_t(void* i) {
153   if (i != nullptr) {
154     MOZ_CRASH("Assertion failed");
155   }
156   gFinalizerTestResources[0]--;
157 }
158 
test_finalizer_null_resource_is_acquired(size_t)159 bool test_finalizer_null_resource_is_acquired(size_t) {
160   return gFinalizerTestResources[0] == 1;
161 }
162 
test_finalizer_cmp_null_t(void * a,void * b)163 bool test_finalizer_cmp_null_t(void* a, void* b) { return a == b; }
164 
165 // Resource type: char*
166 
167 // Acquire resource i
test_finalizer_acq_string_t(int i)168 char* test_finalizer_acq_string_t(int i) {
169   gFinalizerTestResources[i] = 1;
170   if (!gFinalizerTestNames[i]) {
171     char* buf = new char[12];
172     snprintf(buf, 12, "%d", i);
173     gFinalizerTestNames[i] = buf;
174     return buf;
175   }
176   return gFinalizerTestNames[i];
177 }
178 
179 // Release resource i
test_finalizer_rel_string_t(char * i)180 void test_finalizer_rel_string_t(char* i) {
181   int index = atoi(i);
182   if (index < 0 || index >= (int)gFinalizerTestSize) {
183     MOZ_CRASH("Assertion failed");
184   }
185   gFinalizerTestResources[index]--;
186 }
187 
test_finalizer_string_resource_is_acquired(size_t i)188 bool test_finalizer_string_resource_is_acquired(size_t i) {
189   return gFinalizerTestResources[i] == 1;
190 }
191 
test_finalizer_cmp_string_t(char * a,char * b)192 bool test_finalizer_cmp_string_t(char* a, char* b) {
193   return !strncmp(a, b, 10);
194 }
195 
196 // Resource type: myRECT
197 
198 // Acquire resource i
test_finalizer_acq_struct_t(int i)199 myRECT test_finalizer_acq_struct_t(int i) {
200   gFinalizerTestResources[i] = 1;
201   myRECT result = {i, i, i, i};
202   return result;
203 }
204 
205 // Release resource i
test_finalizer_rel_struct_t(myRECT i)206 void test_finalizer_rel_struct_t(myRECT i) {
207   int index = i.top;
208   if (index < 0 || index >= (int)gFinalizerTestSize) {
209     MOZ_CRASH("Assertion failed");
210   }
211   gFinalizerTestResources[index]--;
212 }
213 
test_finalizer_struct_resource_is_acquired(myRECT i)214 bool test_finalizer_struct_resource_is_acquired(myRECT i) {
215   int index = i.top;
216   if (index < 0 || index >= (int)gFinalizerTestSize) {
217     MOZ_CRASH("Assertion failed");
218   }
219   return gFinalizerTestResources[index] == 1;
220 }
221 
test_finalizer_cmp_struct_t(myRECT a,myRECT b)222 bool test_finalizer_cmp_struct_t(myRECT a, myRECT b) { return a.top == b.top; }
223 
224 // Support for checking that we reject nullptr finalizer
test_finalizer_rel_null_function()225 afun* test_finalizer_rel_null_function() { return nullptr; }
226 
test_finalizer_rel_size_t_set_errno(size_t i)227 void test_finalizer_rel_size_t_set_errno(size_t i) {
228   if (--gFinalizerTestResources[i] < 0) {
229     MOZ_CRASH("Assertion failed");
230   }
231   errno = 10;
232 }
233 
reset_errno()234 void reset_errno() { errno = 0; }
235