• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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