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 #include <stdio.h>
22 #include <iostream>
23
24 /**
25 * Type to describe test cases.
26 */
27 typedef struct
28 {
29 jerry_typedarray_type_t typedarray_type; /**< what kind of TypedArray */
30 const char *constructor_name; /**< JS constructor name for TypedArray */
31 uint32_t element_count; /**< number of elements for the TypedArray */
32 uint32_t bytes_per_element; /**< bytes per elment of the given typedarray_type */
33 } test_entry_t;
34
35 /**
36 * Register a JavaScript value in the global object.
37 */
38 static void
register_js_value(const char * name_p,jerry_value_t value)39 register_js_value (const char *name_p, /**< name of the function */
40 jerry_value_t value) /**< function callback */
41 {
42 jerry_value_t global_obj_val = jerry_get_global_object ();
43
44 jerry_value_t name_val = jerry_create_string ((const jerry_char_t *) name_p);
45 jerry_value_t result_val = jerry_set_property (global_obj_val, name_val, value);
46
47 jerry_release_value (name_val);
48 jerry_release_value (global_obj_val);
49
50 jerry_release_value (result_val);
51 } /* register_js_value */
52
53 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)54 assert_handler (const jerry_value_t func_obj_val, /**< function object */
55 const jerry_value_t this_val, /**< this arg */
56 const jerry_value_t args_p[], /**< function arguments */
57 const jerry_length_t args_cnt) /**< number of function arguments */
58 {
59 JERRY_UNUSED (func_obj_val);
60 JERRY_UNUSED (this_val);
61
62 if (jerry_value_is_boolean (args_p[0])
63 && jerry_get_boolean_value (args_p[0]))
64 {
65 return jerry_create_boolean (true);
66 }
67 else
68 {
69 if (args_cnt > 1
70 && jerry_value_is_string (args_p[1]))
71 {
72 jerry_length_t utf8_sz = jerry_get_string_size (args_p[1]);
73 JERRY_VLA (char, string_from_utf8, utf8_sz);
74 string_from_utf8[utf8_sz] = 0;
75
76 jerry_string_to_char_buffer (args_p[1], (jerry_char_t *) string_from_utf8, utf8_sz);
77
78 printf ("JS assert: %s\n", string_from_utf8);
79 }
80 TEST_ASSERT (false);
81 }
82 } /* assert_handler */
83
84 /**
85 * Do simple TypedArray property validation.
86 */
87 static void
test_typedarray_info(jerry_value_t typedarray,jerry_typedarray_type_t typedarray_type,jerry_length_t element_count,jerry_length_t bytes_per_element)88 test_typedarray_info (jerry_value_t typedarray, /**< target TypedArray to query */
89 jerry_typedarray_type_t typedarray_type, /**< expected TypedArray type */
90 jerry_length_t element_count, /**< expected element count */
91 jerry_length_t bytes_per_element) /**< bytes per element for the given type */
92 {
93 TEST_ASSERT (!jerry_value_is_error (typedarray));
94 TEST_ASSERT (jerry_value_is_typedarray (typedarray));
95 TEST_ASSERT (jerry_get_typedarray_type (typedarray) == typedarray_type);
96 TEST_ASSERT (jerry_get_typedarray_length (typedarray) == element_count);
97
98 jerry_length_t byte_length = (uint32_t) -1;
99 jerry_length_t byte_offset = (uint32_t) -1;
100 jerry_value_t arraybuffer = jerry_get_typedarray_buffer (typedarray, &byte_offset, &byte_length);
101 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
102
103 TEST_ASSERT (byte_length == element_count * bytes_per_element);
104 TEST_ASSERT (byte_offset == 0);
105
106 jerry_release_value (arraybuffer);
107 } /* test_typedarray_info */
108
109 /**
110 * Test construction of TypedArrays and validate properties.
111 */
112 static void
test_typedarray_queries(test_entry_t test_entries[])113 test_typedarray_queries (test_entry_t test_entries[]) /**< test cases */
114 {
115 jerry_value_t global_obj_val = jerry_get_global_object ();
116
117 for (uint32_t i = 0; test_entries[i].constructor_name != NULL; i++)
118 {
119 /* Create TypedArray via construct call */
120 {
121 jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) test_entries[i].constructor_name);
122 jerry_value_t prop_value = jerry_get_property (global_obj_val, prop_name);
123 TEST_ASSERT (!jerry_value_is_error (prop_value));
124 jerry_value_t length_arg = jerry_create_number (test_entries[i].element_count);
125
126 jerry_value_t typedarray = jerry_construct_object (prop_value, &length_arg, 1);
127
128 jerry_release_value (prop_name);
129 jerry_release_value (prop_value);
130 jerry_release_value (length_arg);
131
132 test_typedarray_info (typedarray,
133 test_entries[i].typedarray_type,
134 test_entries[i].element_count,
135 test_entries[i].bytes_per_element);
136 jerry_release_value (typedarray);
137 }
138
139 /* Create TypedArray via api call */
140 {
141 jerry_value_t typedarray = jerry_create_typedarray (test_entries[i].typedarray_type,
142 test_entries[i].element_count);
143 test_typedarray_info (typedarray,
144 test_entries[i].typedarray_type,
145 test_entries[i].element_count,
146 test_entries[i].bytes_per_element);
147 jerry_release_value (typedarray);
148 }
149 }
150
151 jerry_release_value (global_obj_val);
152 } /* test_typedarray_queries */
153
154
155
156 /**
157 * Test get/set/delete property by index.
158 */
test_property_by_index(test_entry_t test_entries[])159 static void test_property_by_index (test_entry_t test_entries[])
160 {
161 int test_int_numbers[5] = {-5, -70, 13, 0, 56};
162 double test_double_numbers[5] = {-83.153, -35.15, 0, 13.1, 89.8975};
163 uint8_t test_uint_numbers[5] = {83, 15, 36, 0, 43};
164
165 for (uint32_t i = 0; test_entries[i].constructor_name != NULL; i++)
166 {
167 jerry_value_t test_number;
168 uint32_t test_numbers_length = sizeof (test_int_numbers) / sizeof (int);
169 jerry_value_t typedarray = jerry_create_typedarray (test_entries[i].typedarray_type, test_numbers_length);
170 jerry_typedarray_type_t type = jerry_get_typedarray_type (typedarray);
171
172 jerry_value_t set_result;
173 jerry_value_t get_result;
174
175 switch (type)
176 {
177 case JERRY_TYPEDARRAY_INT8:
178 case JERRY_TYPEDARRAY_INT16:
179 case JERRY_TYPEDARRAY_INT32:
180 {
181 for (uint8_t j = 0; j < test_numbers_length; j++)
182 {
183 test_number = jerry_create_number (test_int_numbers[j]);
184 TEST_ASSERT (!jerry_delete_property_by_index (typedarray, j));
185 set_result = jerry_set_property_by_index (typedarray, j, test_number);
186 get_result = jerry_get_property_by_index (typedarray, j);
187
188 TEST_ASSERT (jerry_value_is_boolean (set_result));
189 TEST_ASSERT (jerry_get_boolean_value (set_result));
190 TEST_ASSERT (!jerry_delete_property_by_index (typedarray, j));
191 TEST_ASSERT (jerry_get_number_value (get_result) == test_int_numbers[j]);
192
193 jerry_release_value (test_number);
194 jerry_release_value (set_result);
195 jerry_release_value (get_result);
196 }
197 break;
198 }
199 case JERRY_TYPEDARRAY_FLOAT32:
200 case JERRY_TYPEDARRAY_FLOAT64:
201 {
202 for (uint8_t j = 0; j < test_numbers_length; j++)
203 {
204 test_number = jerry_create_number (test_double_numbers[j]);
205 TEST_ASSERT (!jerry_delete_property_by_index (typedarray, j));
206 set_result = jerry_set_property_by_index (typedarray, j, test_number);
207 get_result = jerry_get_property_by_index (typedarray, j);
208
209 TEST_ASSERT (jerry_value_is_boolean (set_result));
210 TEST_ASSERT (jerry_get_boolean_value (set_result));
211 TEST_ASSERT (!jerry_delete_property_by_index (typedarray, j));
212
213 double epsilon = pow (10, -5);
214 double get_abs = fabs (jerry_get_number_value (get_result) - test_double_numbers[j]);
215 TEST_ASSERT (get_abs < epsilon);
216
217 jerry_release_value (test_number);
218 jerry_release_value (set_result);
219 jerry_release_value (get_result);
220
221 /* Testing positive and negative infinity */
222 for (uint8_t k = 0; k < 2; k++)
223 {
224 jerry_value_t inf = jerry_create_number_infinity (k);
225 jerry_value_t set_inf = jerry_set_property_by_index (typedarray, 0, inf);
226 TEST_ASSERT (jerry_value_is_boolean (set_inf));
227 TEST_ASSERT (jerry_get_boolean_value (set_inf));
228 jerry_value_t get_inf = jerry_get_property_by_index (typedarray, 0);
229 TEST_ASSERT (isinf (jerry_get_number_value (get_inf)));
230
231 jerry_release_value (inf);
232 jerry_release_value (set_inf);
233 jerry_release_value (get_inf);
234 }
235 }
236 break;
237 }
238 default:
239 {
240 for (uint8_t j = 0; j < test_numbers_length; j++)
241 {
242 test_number = jerry_create_number (test_uint_numbers[j]);
243 TEST_ASSERT (!jerry_delete_property_by_index (typedarray, j));
244 set_result = jerry_set_property_by_index (typedarray, j, test_number);
245 get_result = jerry_get_property_by_index (typedarray, j);
246
247 TEST_ASSERT (jerry_value_is_boolean (set_result));
248 TEST_ASSERT (jerry_get_boolean_value (set_result));
249 TEST_ASSERT (!jerry_delete_property_by_index (typedarray, j));
250 TEST_ASSERT (jerry_get_number_value (get_result) == test_uint_numbers[j]);
251
252 jerry_release_value (test_number);
253 jerry_release_value (set_result);
254 jerry_release_value (get_result);
255 }
256 break;
257 }
258 }
259
260 jerry_value_t set_undefined = jerry_set_property_by_index (typedarray, 100, jerry_create_number (50));
261 TEST_ASSERT (jerry_value_is_error (set_undefined));
262 jerry_value_t get_undefined = jerry_get_property_by_index (typedarray, 100);
263 TEST_ASSERT (jerry_value_is_undefined (get_undefined));
264
265 jerry_release_value (set_undefined);
266 jerry_release_value (get_undefined);
267 jerry_release_value (typedarray);
268 }
269 } /* test_property_by_index */
270
271 static void
test_detached_arraybuffer(void)272 test_detached_arraybuffer (void)
273 {
274 static jerry_typedarray_type_t types[] =
275 {
276 JERRY_TYPEDARRAY_UINT8,
277 JERRY_TYPEDARRAY_UINT8CLAMPED,
278 JERRY_TYPEDARRAY_INT8,
279 JERRY_TYPEDARRAY_UINT16,
280 JERRY_TYPEDARRAY_INT16,
281 JERRY_TYPEDARRAY_UINT32,
282 JERRY_TYPEDARRAY_INT32,
283 JERRY_TYPEDARRAY_FLOAT32,
284 JERRY_TYPEDARRAY_FLOAT64,
285 };
286
287 /* Creating an TypedArray for a detached array buffer with a given length/offset is invalid */
288 {
289 uint8_t buf[1];
290 const uint32_t length = 1;
291 jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buf, NULL);
292 TEST_ASSERT (!jerry_value_is_error (arraybuffer));
293 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
294 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
295
296 jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
297 TEST_ASSERT (!jerry_value_is_error (is_detachable));
298 TEST_ASSERT (jerry_get_boolean_value (is_detachable));
299 jerry_release_value (is_detachable);
300
301 jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
302 TEST_ASSERT (!jerry_value_is_error (res));
303 jerry_release_value (res);
304
305 for (size_t idx = 0; idx < (sizeof (types) / sizeof (types[0])); idx++)
306 {
307 jerry_value_t typedarray = jerry_create_typedarray_for_arraybuffer_sz (types[idx], arraybuffer, 0, 4);
308 TEST_ASSERT (jerry_value_is_error (typedarray));
309 TEST_ASSERT (jerry_get_error_type (typedarray) == JERRY_ERROR_TYPE);
310 jerry_release_value (typedarray);
311 }
312
313 jerry_release_value (arraybuffer);
314 }
315
316 /* Creating an TypedArray for a detached array buffer without length/offset is valid */
317 {
318 uint8_t buf[1];
319 const uint32_t length = 1;
320 jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buf, NULL);
321 TEST_ASSERT (!jerry_value_is_error (arraybuffer));
322 TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
323 TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
324
325 jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
326 TEST_ASSERT (!jerry_value_is_error (is_detachable));
327 TEST_ASSERT (jerry_get_boolean_value (is_detachable));
328 jerry_release_value (is_detachable);
329
330 jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
331 TEST_ASSERT (!jerry_value_is_error (res));
332 jerry_release_value (res);
333
334 for (size_t idx = 0; idx < (sizeof (types) / sizeof (types[0])); idx++)
335 {
336 jerry_value_t typedarray = jerry_create_typedarray_for_arraybuffer (types[idx], arraybuffer);
337 TEST_ASSERT (jerry_value_is_error (typedarray));
338 TEST_ASSERT (jerry_get_error_type (typedarray) == JERRY_ERROR_TYPE);
339 jerry_release_value (typedarray);
340 }
341
342 jerry_release_value (arraybuffer);
343 }
344 } /* test_detached_arraybuffer */
345
346 class TypedarrayTest : public testing::Test{
347 public:
SetUpTestCase()348 static void SetUpTestCase()
349 {
350 GTEST_LOG_(INFO) << "TypedarrayTest SetUpTestCase";
351 }
352
TearDownTestCase()353 static void TearDownTestCase()
354 {
355 GTEST_LOG_(INFO) << "TypedarrayTest TearDownTestCase";
356 }
357
SetUp()358 void SetUp() override {}
TearDown()359 void TearDown() override {}
360
361 };
362 static constexpr size_t JERRY_SCRIPT_MEM_SIZE = 50 * 1024 * 1024;
context_alloc_fn(size_t size,void * cb_data)363 static void* context_alloc_fn(size_t size, void* cb_data)
364 {
365 (void)cb_data;
366 size_t newSize = size > JERRY_SCRIPT_MEM_SIZE ? JERRY_SCRIPT_MEM_SIZE : size;
367 return malloc(newSize);
368 }
369 HWTEST_F(TypedarrayTest, Test001, testing::ext::TestSize.Level1)
370 {
371 jerry_context_t *ctx_p = jerry_create_context (1024, context_alloc_fn, NULL);
372 jerry_port_default_set_current_context (ctx_p);
373 jerry_init (JERRY_INIT_EMPTY);
374
375 if (!jerry_is_feature_enabled (JERRY_FEATURE_TYPEDARRAY))
376 {
377 jerry_port_log (JERRY_LOG_LEVEL_ERROR, "TypedArray is disabled!\n");
378 jerry_cleanup ();
379 return;
380 }
381
382 jerry_value_t function_val = jerry_create_external_function (assert_handler);
383 register_js_value ("assert", function_val);
384 jerry_release_value (function_val);
385
386 test_entry_t test_entries[] =
387 {
388 #define TEST_ENTRY(TYPE, CONSTRUCTOR, COUNT, BYTES_PER_ELEMENT) \
389 { TYPE, CONSTRUCTOR, COUNT, BYTES_PER_ELEMENT }
390
391 TEST_ENTRY (JERRY_TYPEDARRAY_UINT8, "Uint8Array", 12, 1),
392 TEST_ENTRY (JERRY_TYPEDARRAY_UINT8CLAMPED, "Uint8ClampedArray", 12, 1),
393 TEST_ENTRY (JERRY_TYPEDARRAY_INT8, "Int8Array", 12, 1),
394 TEST_ENTRY (JERRY_TYPEDARRAY_UINT16, "Uint16Array", 12, 2),
395 TEST_ENTRY (JERRY_TYPEDARRAY_INT16, "Int16Array", 12, 2),
396 TEST_ENTRY (JERRY_TYPEDARRAY_UINT16, "Uint16Array", 12, 2),
397 TEST_ENTRY (JERRY_TYPEDARRAY_INT32, "Int32Array", 12, 4),
398 TEST_ENTRY (JERRY_TYPEDARRAY_UINT32, "Uint32Array", 12, 4),
399 TEST_ENTRY (JERRY_TYPEDARRAY_FLOAT32, "Float32Array", 12, 4),
400 /* TODO: add check if the float64 is supported */
401 TEST_ENTRY (JERRY_TYPEDARRAY_FLOAT64, "Float64Array", 12, 8),
402
403 TEST_ENTRY (JERRY_TYPEDARRAY_INVALID, NULL, 0, 0)
404 #undef TEST_ENTRY
405 };
406
407 /* Test TypedArray queries */
408 test_typedarray_queries (test_entries);
409
410
411
412
413 test_property_by_index (test_entries);
414 /* test invalid things */
415 {
416 jerry_value_t values[] =
417 {
418 jerry_create_number (11),
419 jerry_create_boolean (false),
420 jerry_create_string ((const jerry_char_t *) "test"),
421 jerry_create_object (),
422 jerry_create_null (),
423 jerry_create_arraybuffer (16),
424 jerry_create_error (JERRY_ERROR_TYPE, (const jerry_char_t *) "error"),
425 jerry_create_undefined (),
426 jerry_create_promise (),
427 };
428
429 for (size_t idx = 0; idx < sizeof (values) / sizeof (values[0]); idx++)
430 {
431 /* A non-TypedArray object should not be regarded a TypedArray. */
432 bool is_typedarray = jerry_value_is_typedarray (values[idx]);
433 TEST_ASSERT (is_typedarray == false);
434
435 /* JERRY_TYPEDARRAY_INVALID should be returned for non-TypedArray objects */
436 jerry_typedarray_type_t type = jerry_get_typedarray_type (values[idx]);
437 TEST_ASSERT (type == JERRY_TYPEDARRAY_INVALID);
438
439 /* Zero should be returned for non-TypedArray objects */
440 jerry_length_t length = jerry_get_typedarray_length (values[idx]);
441 TEST_ASSERT (length == 0);
442
443 /**
444 * Getting the ArrayBuffer from a non-TypedArray object(s) should return an error
445 * and should not modify the output parameter values.
446 */
447 {
448 jerry_length_t offset = 22;
449 jerry_length_t byte_count = 23;
450 TEST_ASSERT (offset == 22);
451 TEST_ASSERT (byte_count == 23);
452 // jerry_release_value (error);
453 }
454
455
456 jerry_release_value (values[idx]);
457 }
458 }
459 test_detached_arraybuffer ();
460 jerry_cleanup ();
461 free(ctx_p);
462 return;
463 }
464