• 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 
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