1 /* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "jerryscript.h"
17 #include "jerryscript-port.h"
18 #include "jerryscript-port-default.h"
19 #include "test-common.h"
20 #include <gtest/gtest.h>
21
22 /**
23 * Register a JavaScript value in the global object.
24 */
25 static void
register_js_value(const char * name_p,jerry_value_t value)26 register_js_value (const char *name_p, /**< name of the function */
27 jerry_value_t value) /**< JS value */
28 {
29 jerry_value_t global_obj_val = jerry_get_global_object ();
30
31 jerry_value_t name_val = jerry_create_string ((const jerry_char_t *) name_p);
32 jerry_value_t result_val = jerry_set_property (global_obj_val, name_val, value);
33 TEST_ASSERT (jerry_value_is_boolean (result_val));
34
35 jerry_release_value (name_val);
36 jerry_release_value (global_obj_val);
37
38 jerry_release_value (result_val);
39 } /* register_js_value */
40
41 static jerry_value_t
assert_handler(const jerry_value_t func_obj_val,const jerry_value_t this_val,const jerry_value_t args_p[],const jerry_length_t args_cnt)42 assert_handler (const jerry_value_t func_obj_val, /**< function object */
43 const jerry_value_t this_val, /**< this arg */
44 const jerry_value_t args_p[], /**< function arguments */
45 const jerry_length_t args_cnt) /**< number of function arguments */
46 {
47 JERRY_UNUSED (func_obj_val);
48 JERRY_UNUSED (this_val);
49
50 if (args_cnt > 0
51 && jerry_value_is_boolean (args_p[0])
52 && jerry_get_boolean_value (args_p[0]))
53 {
54 return jerry_create_boolean (true);
55 }
56
57 if (args_cnt > 1
58 && jerry_value_is_string (args_p[1]))
59 {
60 jerry_length_t utf8_sz = jerry_get_string_size (args_p[1]);
61 JERRY_VLA (char, string_from_utf8, utf8_sz);
62 string_from_utf8[utf8_sz] = 0;
63
64 jerry_string_to_char_buffer (args_p[1], (jerry_char_t *) string_from_utf8, utf8_sz);
65
66 printf ("JS assert: %s\n", string_from_utf8);
67 }
68
69 TEST_ASSERT (false);
70 } /* assert_handler */
71
72 static bool callback_called = false;
73 static bool detach_free_callback_called = false;
74
test_free_cb(void * buffer)75 static void test_free_cb (void *buffer) /**< buffer to free (if needed) */
76 {
77 (void) buffer;
78 callback_called = true;
79 } /* test_free_cb */
80
test_detach_free_cb(void * buffer)81 static void test_detach_free_cb (void *buffer) /**< buffer to free */
82 {
83 free (buffer);
84 detach_free_callback_called = true;
85 } /* test_detach_free_cb */
86
87 class ArrayBufferTest : public testing::Test{
88 public:
SetUpTestCase()89 static void SetUpTestCase()
90 {
91 GTEST_LOG_(INFO) << "ArrayBufferTest SetUpTestCase";
92 }
93
TearDownTestCase()94 static void TearDownTestCase()
95 {
96 GTEST_LOG_(INFO) << "ArrayBufferTest TearDownTestCase";
97 }
98
SetUp()99 void SetUp() override {}
TearDown()100 void TearDown() override {}
101
102 };
103 static constexpr size_t JERRY_SCRIPT_MEM_SIZE = 50 * 1024 * 1024;
context_alloc_fn(size_t size,void * cb_data)104 static void* context_alloc_fn(size_t size, void* cb_data)
105 {
106 (void)cb_data;
107 size_t newSize = size > JERRY_SCRIPT_MEM_SIZE ? JERRY_SCRIPT_MEM_SIZE : size;
108 return malloc(newSize);
109 }
110 HWTEST_F(ArrayBufferTest, Test001, testing::ext::TestSize.Level1)
111 {
112 jerry_context_t *ctx_p = jerry_create_context (1024, context_alloc_fn, NULL);
113 jerry_port_default_set_current_context (ctx_p);
114 jerry_init (JERRY_INIT_EMPTY);
115
116 if (!jerry_is_feature_enabled (JERRY_FEATURE_TYPEDARRAY))
117 {
118 jerry_port_log (JERRY_LOG_LEVEL_ERROR, "ArrayBuffer is disabled!\n");
119 jerry_cleanup ();
120 return;
121 }
122
123 jerry_value_t function_val = jerry_create_external_function (assert_handler);
124 register_js_value ("assert", function_val);
125 jerry_release_value (function_val);
126
127 /* Test array buffer queries */
128 {
129 const jerry_char_t eval_arraybuffer_src[] = "new ArrayBuffer (10)";
130 jerry_value_t eval_arraybuffer = jerry_eval (eval_arraybuffer_src,
131 sizeof (eval_arraybuffer_src) - 1,
132 JERRY_PARSE_STRICT_MODE);
133 TEST_ASSERT (!jerry_value_is_error (eval_arraybuffer));
134 TEST_ASSERT (jerry_value_is_arraybuffer (eval_arraybuffer));
135 TEST_ASSERT (jerry_get_arraybuffer_byte_length (eval_arraybuffer) == 10);
136 jerry_release_value (eval_arraybuffer);
137 }
138
139 /* Test array buffer creation */
140 {
141 const uint32_t length = 15;
142 jerry_value_t arraybuffer = jerry_create_arraybuffer (length);
143 TEST_ASSERT (!jerry_value_is_error (arraybuffer));
144 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
145 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
146 jerry_release_value (arraybuffer);
147 }
148
149 /* Test zero length ArrayBuffer read */
150 {
151 const uint32_t length = 0;
152 jerry_value_t arraybuffer = jerry_create_arraybuffer (length);
153 TEST_ASSERT (!jerry_value_is_error (arraybuffer));
154 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
155 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
156
157 uint8_t data[20];
158 memset (data, 11, 20);
159
160 jerry_length_t bytes_read = jerry_arraybuffer_read (arraybuffer, 0, data, 20);
161 TEST_ASSERT (bytes_read == 0);
162
163 for (int i = 0; i < 20; i++)
164 {
165 TEST_ASSERT (data[i] == 11);
166 }
167
168 jerry_release_value (arraybuffer);
169 }
170
171 /* Test zero length ArrayBuffer write */
172 {
173 const uint32_t length = 0;
174 jerry_value_t arraybuffer = jerry_create_arraybuffer (length);
175 TEST_ASSERT (!jerry_value_is_error (arraybuffer));
176 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
177 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
178
179 uint8_t data[20];
180 memset (data, 11, 20);
181
182 jerry_length_t bytes_written = jerry_arraybuffer_write (arraybuffer, 0, data, 20);
183 TEST_ASSERT (bytes_written == 0);
184
185 jerry_release_value (arraybuffer);
186 }
187
188 /* Test zero length external ArrayBuffer */
189 {
190 const uint32_t length = 0;
191 jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, NULL, NULL);
192 TEST_ASSERT (!jerry_value_is_error (arraybuffer));
193 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
194 TEST_ASSERT (jerry_is_arraybuffer_detachable (arraybuffer));
195 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
196
197 uint8_t data[20];
198 memset (data, 11, 20);
199
200 jerry_length_t bytes_written = jerry_arraybuffer_write (arraybuffer, 0, data, 20);
201 TEST_ASSERT (bytes_written == 0);
202
203 jerry_release_value (arraybuffer);
204 }
205
206 /* Test ArrayBuffer with buffer allocated externally */
207 {
208 const uint32_t buffer_size = 15;
209 const uint8_t base_value = 51;
210
211 JERRY_VLA (uint8_t, buffer_p, buffer_size);
212 memset (buffer_p, base_value, buffer_size);
213
214 jerry_value_t arrayb = jerry_create_arraybuffer_external (buffer_size, buffer_p, test_free_cb);
215 uint8_t new_value = 123;
216 jerry_length_t copied = jerry_arraybuffer_write (arrayb, 0, &new_value, 1);
217 TEST_ASSERT (copied == 1);
218 TEST_ASSERT (buffer_p[0] == new_value);
219 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arrayb) == buffer_size);
220
221 for (uint32_t i = 1; i < buffer_size; i++)
222 {
223 TEST_ASSERT (buffer_p[i] == base_value);
224 }
225
226 JERRY_VLA (uint8_t, test_buffer, buffer_size);
227 jerry_length_t read = jerry_arraybuffer_read (arrayb, 0, test_buffer, buffer_size);
228 TEST_ASSERT (read == buffer_size);
229 TEST_ASSERT (test_buffer[0] == new_value);
230
231 for (uint32_t i = 1; i < buffer_size; i++)
232 {
233 TEST_ASSERT (test_buffer[i] == base_value);
234 }
235
236 TEST_ASSERT (jerry_value_is_arraybuffer (arrayb));
237 jerry_release_value (arrayb);
238 }
239
240 /* Test ArrayBuffer external memory map/unmap */
241 {
242 const uint32_t buffer_size = 20;
243 /* cppcheck-suppress variableScope */
244 JERRY_VLA (uint8_t, buffer_p, buffer_size);
245 {
246 jerry_value_t input_buffer = jerry_create_arraybuffer_external (buffer_size, buffer_p, NULL);
247 register_js_value ("input_buffer", input_buffer);
248 jerry_release_value (input_buffer);
249 }
250
251 const jerry_char_t eval_arraybuffer_src[] = TEST_STRING_LITERAL (
252 "var array = new Uint8Array(input_buffer);"
253 "for (var i = 0; i < array.length; i++)"
254 "{"
255 " array[i] = i * 2;"
256 "};"
257 "array.buffer"
258 );
259 jerry_value_t buffer = jerry_eval (eval_arraybuffer_src,
260 sizeof (eval_arraybuffer_src) - 1,
261 JERRY_PARSE_STRICT_MODE);
262
263 TEST_ASSERT (!jerry_value_is_error (buffer));
264 TEST_ASSERT (jerry_value_is_arraybuffer (buffer));
265 TEST_ASSERT (jerry_get_arraybuffer_byte_length (buffer) == 20);
266
267 uint8_t *const data = jerry_get_arraybuffer_pointer (buffer);
268
269 /* test memory read */
270 for (int i = 0; i < 20; i++)
271 {
272 TEST_ASSERT (data[i] == (uint8_t) (i * 2));
273 }
274
275 /* "upload" new data */
276 double sum = 0;
277 for (int i = 0; i < 20; i++)
278 {
279 data[i] = (uint8_t) (i * 3);
280 sum += data[i];
281 }
282
283 jerry_release_value (buffer);
284 }
285
286 /* Test internal ArrayBuffer detach */
287 {
288 const uint32_t length = 1;
289 jerry_value_t arraybuffer = jerry_create_arraybuffer (length);
290 TEST_ASSERT (!jerry_value_is_error (arraybuffer));
291 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
292 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
293
294 jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
295 TEST_ASSERT (!jerry_value_is_error (is_detachable));
296 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
297 jerry_release_value (is_detachable);
298
299 // jerry_release_value (res);
300 jerry_release_value (arraybuffer);
301 }
302
303 /* Test external ArrayBuffer detach */
304 {
305 uint8_t buf[1];
306 const uint32_t length = 1;
307 jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buf, NULL);
308 TEST_ASSERT (!jerry_value_is_error (arraybuffer));
309 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
310 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
311
312 jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
313 TEST_ASSERT (!jerry_value_is_error (is_detachable));
314 TEST_ASSERT (jerry_get_boolean_value (is_detachable));
315 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
316 jerry_release_value (is_detachable);
317
318 jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
319 TEST_ASSERT (!jerry_value_is_error (res));
320 TEST_ASSERT (jerry_get_arraybuffer_pointer (arraybuffer) == NULL);
321 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == 0);
322
323 is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
324 TEST_ASSERT (!jerry_value_is_error (is_detachable));
325 TEST_ASSERT (!jerry_get_boolean_value (is_detachable));
326 jerry_release_value (is_detachable);
327
328 jerry_release_value (res);
329 jerry_release_value (arraybuffer);
330 }
331
332 /* Test external ArrayBuffer with callback detach */
333 {
334 const uint32_t length = 8;
335 uint8_t *buf = (uint8_t *) malloc (length);
336 jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buf, test_detach_free_cb);
337 TEST_ASSERT (!jerry_value_is_error (arraybuffer));
338 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
339 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
340
341 jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
342 TEST_ASSERT (!jerry_value_is_error (is_detachable));
343 TEST_ASSERT (jerry_get_boolean_value (is_detachable));
344 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
345 jerry_release_value (is_detachable);
346
347 jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
348 TEST_ASSERT (!jerry_value_is_error (res));
349 TEST_ASSERT (jerry_get_arraybuffer_pointer (arraybuffer) == NULL);
350 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == 0);
351
352 is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
353 TEST_ASSERT (!jerry_value_is_error (is_detachable));
354 TEST_ASSERT (!jerry_get_boolean_value (is_detachable));
355 jerry_release_value (is_detachable);
356
357 jerry_release_value (res);
358 jerry_release_value (arraybuffer);
359 }
360
361 jerry_cleanup ();
362
363 TEST_ASSERT (callback_called == true);
364 free(ctx_p);
365 return;
366 }
367