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#define T(op, lhs, rhs, res) \
23  { op, lhs, rhs, res }
24
25#define T_NAN(op, lhs, rhs) \
26  { op, lhs, rhs }
27
28#define T_ERR(op, lsh, rhs) \
29  T_NAN (op, lsh, rhs)
30
31#define T_ARI(lhs, rhs) \
32  T_NAN (JERRY_BIN_OP_SUB, lhs, rhs), \
33  T_NAN (JERRY_BIN_OP_MUL, lhs, rhs), \
34  T_NAN (JERRY_BIN_OP_DIV, lhs, rhs), \
35  T_NAN (JERRY_BIN_OP_REM, lhs, rhs)
36
37typedef struct
38{
39  jerry_binary_operation_t op;
40  jerry_value_t lhs;
41  jerry_value_t rhs;
42  jerry_value_t expected;
43} test_entry_t;
44
45typedef struct
46{
47  jerry_binary_operation_t op;
48  jerry_value_t lhs;
49  jerry_value_t rhs;
50} test_nan_entry_t;
51
52typedef test_nan_entry_t test_error_entry_t;
53class ApiBinaryOperationsArithmeticsTest : public testing::Test{
54public:
55    static void SetUpTestCase()
56    {
57        GTEST_LOG_(INFO) << "ApiBinaryOperationsArithmeticsTest SetUpTestCase";
58    }
59
60    static void TearDownTestCase()
61    {
62        GTEST_LOG_(INFO) << "ApiBinaryOperationsArithmeticsTest TearDownTestCase";
63    }
64
65    void SetUp() override {}
66    void TearDown() override {}
67
68};
69
70static constexpr size_t JERRY_SCRIPT_MEM_SIZE = 50 * 1024 * 1024;
71static void* context_alloc_fn(size_t size, void* cb_data)
72{
73    (void)cb_data;
74    size_t newSize = size > JERRY_SCRIPT_MEM_SIZE ? JERRY_SCRIPT_MEM_SIZE : size;
75    return malloc(newSize);
76}
77HWTEST_F(ApiBinaryOperationsArithmeticsTest, Test001, testing::ext::TestSize.Level1)
78{
79  jerry_context_t* ctx_p = jerry_create_context(1024 * 1024 * 50, context_alloc_fn, NULL);
80  jerry_port_default_set_current_context(ctx_p);
81  TEST_INIT ();
82
83  jerry_init (JERRY_INIT_EMPTY);
84
85  jerry_value_t obj1 = jerry_eval ((const jerry_char_t *) "o={x:1};o", 9, JERRY_PARSE_NO_OPTS);
86  jerry_value_t obj2 = jerry_eval ((const jerry_char_t *) "o={x:1};o", 9, JERRY_PARSE_NO_OPTS);
87  jerry_value_t err1 = jerry_create_error (JERRY_ERROR_SYNTAX, (const jerry_char_t *) "error");
88
89  test_nan_entry_t test_nans[] =
90  {
91    /* Testing addition (+) */
92    T_NAN (JERRY_BIN_OP_ADD, jerry_create_number (3.1), jerry_create_undefined ()),
93    T_NAN (JERRY_BIN_OP_ADD, jerry_create_undefined (), jerry_create_undefined ()),
94    T_NAN (JERRY_BIN_OP_ADD, jerry_create_undefined (), jerry_create_null ()),
95
96    /* Testing subtraction (-), multiplication (*), division (/), remainder (%) */
97    T_ARI (jerry_create_number (3.1), jerry_create_undefined ()),
98    T_ARI (jerry_create_string ((const jerry_char_t *) "foo"), jerry_create_string ((const jerry_char_t *) "bar")),
99    T_ARI (jerry_create_string ((const jerry_char_t *) "foo"), jerry_create_undefined ()),
100    T_ARI (jerry_create_string ((const jerry_char_t *) "foo"), jerry_create_null ()),
101    T_ARI (jerry_create_string ((const jerry_char_t *) "foo"), jerry_create_number (5.0)),
102    T_ARI (jerry_create_undefined (), jerry_create_string ((const jerry_char_t *) "foo")),
103    T_ARI (jerry_create_null (), jerry_create_string ((const jerry_char_t *) "foo")),
104    T_ARI (jerry_create_number (5.0), jerry_create_string ((const jerry_char_t *) "foo")),
105    T_ARI (jerry_create_undefined (), jerry_create_undefined ()),
106    T_ARI (jerry_create_undefined (), jerry_create_null ()),
107    T_ARI (jerry_create_null (), jerry_create_undefined ()),
108    T_ARI (jerry_acquire_value (obj1), jerry_acquire_value (obj1)),
109    T_ARI (jerry_acquire_value (obj1), jerry_acquire_value (obj2)),
110    T_ARI (jerry_acquire_value (obj2), jerry_acquire_value (obj1)),
111    T_ARI (jerry_acquire_value (obj2), jerry_create_undefined ()),
112    T_ARI (jerry_acquire_value (obj1), jerry_create_string ((const jerry_char_t *) "foo")),
113    T_ARI (jerry_acquire_value (obj1), jerry_create_null ()),
114    T_ARI (jerry_acquire_value (obj1), jerry_create_boolean (true)),
115    T_ARI (jerry_acquire_value (obj1), jerry_create_boolean (false)),
116    T_ARI (jerry_acquire_value (obj1), jerry_create_number (5.0)),
117
118    /* Testing division (/) */
119    T_NAN (JERRY_BIN_OP_DIV, jerry_create_boolean (false), jerry_create_boolean (false)),
120    T_NAN (JERRY_BIN_OP_DIV, jerry_create_number (0.0), jerry_create_number (0.0)),
121    T_NAN (JERRY_BIN_OP_DIV, jerry_create_null (), jerry_create_null ()),
122
123    /* Testing remainder (%) */
124    T_NAN (JERRY_BIN_OP_REM, jerry_create_boolean (true), jerry_create_boolean (false)),
125    T_NAN (JERRY_BIN_OP_REM, jerry_create_boolean (false), jerry_create_boolean (false)),
126    T_NAN (JERRY_BIN_OP_REM, jerry_create_number (0.0), jerry_create_number (0.0)),
127    T_NAN (JERRY_BIN_OP_REM, jerry_create_null (), jerry_create_null ()),
128  };
129
130  for (uint32_t idx = 0; idx < sizeof (test_nans) / sizeof (test_nan_entry_t); idx++)
131  {
132    jerry_value_t result = jerry_binary_operation (test_nans[idx].op, test_nans[idx].lhs, test_nans[idx].rhs);
133    TEST_ASSERT (jerry_value_is_number (result));
134
135    double num = jerry_get_number_value (result);
136
137    TEST_ASSERT (num != num);
138
139    jerry_release_value (test_nans[idx].lhs);
140    jerry_release_value (test_nans[idx].rhs);
141    jerry_release_value (result);
142  }
143
144  test_entry_t tests[] =
145  {
146    /* Testing addition (+) */
147    T (JERRY_BIN_OP_ADD, jerry_create_number (5.0), jerry_create_number (5.0), jerry_create_number (10.0)),
148    T (JERRY_BIN_OP_ADD, jerry_create_number (3.1), jerry_create_number (10), jerry_create_number (13.1)),
149    T (JERRY_BIN_OP_ADD, jerry_create_number (3.1), jerry_create_boolean (true), jerry_create_number (4.1)),
150    T (JERRY_BIN_OP_ADD,
151       jerry_create_string ((const jerry_char_t *) "foo"),
152       jerry_create_string ((const jerry_char_t *) "bar"),
153       jerry_create_string ((const jerry_char_t *) "foobar")),
154    T (JERRY_BIN_OP_ADD,
155       jerry_create_string ((const jerry_char_t *) "foo"),
156       jerry_create_undefined (),
157       jerry_create_string ((const jerry_char_t *) "fooundefined")),
158    T (JERRY_BIN_OP_ADD,
159       jerry_create_string ((const jerry_char_t *) "foo"),
160       jerry_create_null (),
161       jerry_create_string ((const jerry_char_t *) "foonull")),
162    T (JERRY_BIN_OP_ADD,
163       jerry_create_string ((const jerry_char_t *) "foo"),
164       jerry_create_number (5.0),
165       jerry_create_string ((const jerry_char_t *) "foo5")),
166
167    T (JERRY_BIN_OP_ADD, jerry_create_null (), jerry_create_null (), jerry_create_number (0.0)),
168    T (JERRY_BIN_OP_ADD, jerry_create_boolean (true), jerry_create_boolean (true), jerry_create_number (2.0)),
169    T (JERRY_BIN_OP_ADD, jerry_create_boolean (true), jerry_create_boolean (false), jerry_create_number (1.0)),
170    T (JERRY_BIN_OP_ADD, jerry_create_boolean (false), jerry_create_boolean (true), jerry_create_number (1.0)),
171    T (JERRY_BIN_OP_ADD, jerry_create_boolean (false), jerry_create_boolean (false), jerry_create_number (0.0)),
172    T (JERRY_BIN_OP_ADD,
173       jerry_acquire_value (obj1),
174       jerry_acquire_value (obj1),
175       jerry_create_string ((const jerry_char_t *) "[object Object][object Object]")),
176    T (JERRY_BIN_OP_ADD,
177       jerry_acquire_value (obj1),
178       jerry_acquire_value (obj2),
179       jerry_create_string ((const jerry_char_t *) "[object Object][object Object]")),
180    T (JERRY_BIN_OP_ADD,
181       jerry_acquire_value (obj2),
182       jerry_acquire_value (obj1),
183       jerry_create_string ((const jerry_char_t *) "[object Object][object Object]")),
184    T (JERRY_BIN_OP_ADD,
185       jerry_acquire_value (obj1),
186       jerry_create_null (),
187       jerry_create_string ((const jerry_char_t *) "[object Object]null")),
188    T (JERRY_BIN_OP_ADD,
189       jerry_acquire_value (obj1),
190       jerry_create_undefined (),
191       jerry_create_string ((const jerry_char_t *) "[object Object]undefined")),
192    T (JERRY_BIN_OP_ADD,
193       jerry_acquire_value (obj1),
194       jerry_create_boolean (true),
195       jerry_create_string ((const jerry_char_t *) "[object Object]true")),
196    T (JERRY_BIN_OP_ADD,
197       jerry_acquire_value (obj1),
198       jerry_create_boolean (false),
199       jerry_create_string ((const jerry_char_t *) "[object Object]false")),
200    T (JERRY_BIN_OP_ADD,
201       jerry_acquire_value (obj1),
202       jerry_create_number (5.0),
203       jerry_create_string ((const jerry_char_t *) "[object Object]5")),
204    T (JERRY_BIN_OP_ADD,
205       jerry_acquire_value (obj1),
206       jerry_create_string ((const jerry_char_t *) "foo"),
207       jerry_create_string ((const jerry_char_t *) "[object Object]foo")),
208
209    /* Testing subtraction (-) */
210    T (JERRY_BIN_OP_SUB, jerry_create_number (5.0), jerry_create_number (5.0), jerry_create_number (0.0)),
211    T (JERRY_BIN_OP_SUB, jerry_create_number (3.1), jerry_create_number (10), jerry_create_number (-6.9)),
212    T (JERRY_BIN_OP_SUB, jerry_create_number (3.1), jerry_create_boolean (true), jerry_create_number (2.1)),
213    T (JERRY_BIN_OP_SUB, jerry_create_boolean (true), jerry_create_boolean (true), jerry_create_number (0.0)),
214    T (JERRY_BIN_OP_SUB, jerry_create_boolean (true), jerry_create_boolean (false), jerry_create_number (1.0)),
215    T (JERRY_BIN_OP_SUB, jerry_create_boolean (false), jerry_create_boolean (true), jerry_create_number (-1.0)),
216    T (JERRY_BIN_OP_SUB, jerry_create_boolean (false), jerry_create_boolean (false), jerry_create_number (0.0)),
217    T (JERRY_BIN_OP_SUB, jerry_create_null (), jerry_create_null (), jerry_create_number (-0.0)),
218
219    /* Testing multiplication (*) */
220    T (JERRY_BIN_OP_MUL, jerry_create_number (5.0), jerry_create_number (5.0), jerry_create_number (25.0)),
221    T (JERRY_BIN_OP_MUL, jerry_create_number (3.1), jerry_create_number (10), jerry_create_number (31)),
222    T (JERRY_BIN_OP_MUL, jerry_create_number (3.1), jerry_create_boolean (true), jerry_create_number (3.1)),
223    T (JERRY_BIN_OP_MUL, jerry_create_boolean (true), jerry_create_boolean (true), jerry_create_number (1.0)),
224    T (JERRY_BIN_OP_MUL, jerry_create_boolean (true), jerry_create_boolean (false), jerry_create_number (0.0)),
225    T (JERRY_BIN_OP_MUL, jerry_create_boolean (false), jerry_create_boolean (true), jerry_create_number (0.0)),
226    T (JERRY_BIN_OP_MUL, jerry_create_boolean (false), jerry_create_boolean (false), jerry_create_number (0.0)),
227    T (JERRY_BIN_OP_MUL, jerry_create_null (), jerry_create_null (), jerry_create_number (0.0)),
228
229    /* Testing division (/) */
230    T (JERRY_BIN_OP_DIV, jerry_create_number (5.0), jerry_create_number (5.0), jerry_create_number (1.0)),
231    T (JERRY_BIN_OP_DIV, jerry_create_number (3.1), jerry_create_number (10), jerry_create_number (0.31)),
232    T (JERRY_BIN_OP_DIV, jerry_create_number (3.1), jerry_create_boolean (true), jerry_create_number (3.1)),
233    T (JERRY_BIN_OP_DIV, jerry_create_boolean (true), jerry_create_boolean (true), jerry_create_number (1.0)),
234    T (JERRY_BIN_OP_DIV,
235       jerry_create_boolean (true),
236       jerry_create_boolean (false),
237       jerry_create_number_infinity (false)),
238    T (JERRY_BIN_OP_DIV, jerry_create_boolean (false), jerry_create_boolean (true), jerry_create_number (0.0)),
239
240    /* Testing remainder (%) */
241    T (JERRY_BIN_OP_REM, jerry_create_number (5.0), jerry_create_number (5.0), jerry_create_number (0.0)),
242    T (JERRY_BIN_OP_REM, jerry_create_number (5.0), jerry_create_number (2.0), jerry_create_number (1.0)),
243    T (JERRY_BIN_OP_REM, jerry_create_number (3.1), jerry_create_number (10), jerry_create_number (3.1)),
244    T (JERRY_BIN_OP_REM,
245       jerry_create_number (3.1),
246       jerry_create_boolean (true),
247       jerry_create_number (0.10000000000000009)),
248    T (JERRY_BIN_OP_REM, jerry_create_boolean (true), jerry_create_boolean (true), jerry_create_number (0.0)),
249    T (JERRY_BIN_OP_REM, jerry_create_boolean (false), jerry_create_boolean (true), jerry_create_number (0.0)),
250
251  };
252
253  for (uint32_t idx = 0; idx < sizeof (tests) / sizeof (test_entry_t); idx++)
254  {
255    jerry_value_t result = jerry_binary_operation (tests[idx].op, tests[idx].lhs, tests[idx].rhs);
256    TEST_ASSERT (!jerry_value_is_error (result));
257
258    jerry_value_t equals = jerry_binary_operation (JERRY_BIN_OP_STRICT_EQUAL, result, tests[idx].expected);
259    TEST_ASSERT (jerry_value_is_boolean (equals) && jerry_get_boolean_value (equals));
260    jerry_release_value (equals);
261
262    jerry_release_value (tests[idx].lhs);
263    jerry_release_value (tests[idx].rhs);
264    jerry_release_value (tests[idx].expected);
265    jerry_release_value (result);
266  }
267
268  jerry_value_t obj3 = jerry_eval ((const jerry_char_t *) "o={valueOf:function(){throw 5}};o", 33, JERRY_PARSE_NO_OPTS);
269
270  test_error_entry_t error_tests[] =
271  {
272    /* Testing addition (+) */
273    T_ERR (JERRY_BIN_OP_ADD, jerry_acquire_value (err1), jerry_acquire_value (err1)),
274    T_ERR (JERRY_BIN_OP_ADD, jerry_acquire_value (err1), jerry_create_undefined ()),
275    T_ERR (JERRY_BIN_OP_ADD, jerry_create_undefined (), jerry_acquire_value (err1)),
276
277    /* Testing subtraction (-), multiplication (*), division (/), remainder (%) */
278    T_ARI (jerry_acquire_value (err1), jerry_acquire_value (err1)),
279    T_ARI (jerry_acquire_value (err1), jerry_create_undefined ()),
280    T_ARI (jerry_create_undefined (), jerry_acquire_value (err1)),
281
282    /* Testing addition (+) */
283    T_ERR (JERRY_BIN_OP_ADD, jerry_acquire_value (obj3), jerry_create_undefined ()),
284    T_ERR (JERRY_BIN_OP_ADD, jerry_acquire_value (obj3), jerry_create_null ()),
285    T_ERR (JERRY_BIN_OP_ADD, jerry_acquire_value (obj3), jerry_create_boolean (true)),
286    T_ERR (JERRY_BIN_OP_ADD, jerry_acquire_value (obj3), jerry_create_boolean (false)),
287    T_ERR (JERRY_BIN_OP_ADD, jerry_acquire_value (obj3), jerry_acquire_value (obj2)),
288    T_ERR (JERRY_BIN_OP_ADD, jerry_acquire_value (obj3), jerry_create_string ((const jerry_char_t *) "foo")),
289
290    /* Testing subtraction (-), multiplication (*), division (/), remainder (%) */
291    T_ARI (jerry_acquire_value (obj3), jerry_create_undefined ()),
292    T_ARI (jerry_acquire_value (obj3), jerry_create_null ()),
293    T_ARI (jerry_acquire_value (obj3), jerry_create_boolean (true)),
294    T_ARI (jerry_acquire_value (obj3), jerry_create_boolean (false)),
295    T_ARI (jerry_acquire_value (obj3), jerry_acquire_value (obj2)),
296    T_ARI (jerry_acquire_value (obj3), jerry_create_string ((const jerry_char_t *) "foo")),
297  };
298
299  for (uint32_t idx = 0; idx < sizeof (error_tests) / sizeof (test_error_entry_t); idx++)
300  {
301    jerry_value_t result = jerry_binary_operation (tests[idx].op, error_tests[idx].lhs, error_tests[idx].rhs);
302    TEST_ASSERT (jerry_value_is_error (result));
303    jerry_release_value (error_tests[idx].lhs);
304    jerry_release_value (error_tests[idx].rhs);
305    jerry_release_value (result);
306  }
307
308  jerry_release_value (obj1);
309  jerry_release_value (obj2);
310  jerry_release_value (obj3);
311  jerry_release_value (err1);
312
313  jerry_cleanup ();
314  free (ctx_p);
315}
316