*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "jerryscript.h"
#include "jerryscript-port.h"
#include "jerryscript-port-default.h"
#include "test-common.h"
#include <gtest/gtest.h>
static bool
count_objects (jerry_value_t object, void *user_arg)
{
(void) object;
TEST_ASSERT (user_arg != NULL);
int *counter = (int *) user_arg;
(*counter)++;
return true;
}
static void
test_container (void)
{
jerry_value_t global = jerry_get_global_object ();
jerry_value_t map_str = jerry_create_string ((const jerry_char_t *) "Map");
jerry_value_t map_result = jerry_get_property (global, map_str);
jerry_type_t type = jerry_value_get_type (map_result);
jerry_release_value (map_result);
jerry_release_value (map_str);
jerry_release_value (global);
if (type != JERRY_TYPE_FUNCTION)
{
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Container based test is disabled!\n");
return;
}
{
const char array_str[] = "var DEMO = [[1, 2], [3, 4]]; DEMO";
jerry_value_t array = jerry_eval ((const jerry_char_t *) array_str, sizeof (array_str) - 1, 0);
TEST_ASSERT (jerry_value_is_object (array));
TEST_ASSERT (!jerry_value_is_error (array));
jerry_release_value (array);
}
const char eval_str[] = "new Map (DEMO)";
{
jerry_value_t result = jerry_eval ((const jerry_char_t *) eval_str, sizeof (eval_str) - 1, 0);
TEST_ASSERT (jerry_value_is_object (result));
TEST_ASSERT (!jerry_value_is_error (result));
jerry_release_value (result);
}
jerry_gc (JERRY_GC_PRESSURE_LOW);
int start_count = 0;
jerry_objects_foreach (count_objects, &start_count);
jerry_value_t result = jerry_eval ((const jerry_char_t *) eval_str, sizeof (eval_str) - 1, 0);
jerry_gc (JERRY_GC_PRESSURE_LOW);
int end_count = 0;
jerry_objects_foreach (count_objects, &end_count);
ASSERT_TRUE (!(end_count > start_count));
ASSERT_TRUE (!((end_count - start_count) == 1));
jerry_release_value (result);
}
static void
test_internal_prop (void)
{
{
jerry_value_t object = jerry_create_object ();
jerry_release_value (object);
}
int before_object_count = 0;
jerry_objects_foreach (count_objects, &before_object_count);
jerry_value_t object = jerry_create_object ();
int after_object_count = 0;
{
jerry_objects_foreach (count_objects, &after_object_count);
TEST_ASSERT (after_object_count > before_object_count);
TEST_ASSERT ((after_object_count - before_object_count) == 1);
}
jerry_value_t internal_prop_name = jerry_create_string ((const jerry_char_t *) "hidden_foo");
jerry_value_t internal_prop_object = jerry_create_object ();
bool internal_result = jerry_set_internal_property (object, internal_prop_name, internal_prop_object);
TEST_ASSERT (internal_result == true);
jerry_release_value (internal_prop_name);
jerry_release_value (internal_prop_object);
{
int after_internal_count = 0;
jerry_objects_foreach (count_objects, &after_internal_count);
TEST_ASSERT (after_internal_count > after_object_count);
TEST_ASSERT ((after_internal_count - after_object_count) == 1);
}
jerry_release_value (object);
}
static int test_data = 1;
static void free_test_data (void *data_p)
{
TEST_ASSERT ((int *) data_p == &test_data);
}
static const jerry_object_native_info_t test_info =
{
.free_cb = free_test_data
};
static const jerry_char_t strict_equal_source[] = "var x = function(a, b) {return a === b;}; x";
static bool
find_test_object_by_data (const jerry_value_t candidate,
void *object_data_p,
void *context_p)
{
if (object_data_p == &test_data)
{
*((jerry_value_t *) context_p) = jerry_acquire_value (candidate);
return false;
}
return true;
}
static bool
find_test_object_by_property (const jerry_value_t candidate,
void *context_p)
{
jerry_value_t *args_p = (jerry_value_t *) context_p;
jerry_value_t result = jerry_has_property (candidate, args_p[0]);
bool has_property = (!jerry_value_is_error (result) && jerry_get_boolean_value (result));
if (has_property)
{
args_p[1] = jerry_acquire_value (candidate);
}
jerry_release_value (result);
return !has_property;
}
class ObjectsForeachTest : public testing::Test{
public:
static void SetUpTestCase()
{
GTEST_LOG_(INFO) << "ObjectsForeachTest SetUpTestCase";
}
static void TearDownTestCase()
{
GTEST_LOG_(INFO) << "ObjectsForeachTest TearDownTestCase";
}
void SetUp() override {}
void TearDown() override {}
};
static constexpr size_t JERRY_SCRIPT_MEM_SIZE = 50 * 1024 * 1024;
static void* context_alloc_fn(size_t size, void* cb_data)
{
(void)cb_data;
size_t newSize = size > JERRY_SCRIPT_MEM_SIZE ? JERRY_SCRIPT_MEM_SIZE : size;
return malloc(newSize);
}
HWTEST_F(ObjectsForeachTest, Test001, testing::ext::TestSize.Level1)
{
jerry_context_t *ctx_p = jerry_create_context (1024, context_alloc_fn, NULL);
jerry_port_default_set_current_context (ctx_p);
jerry_init (JERRY_INIT_EMPTY);
jerry_value_t parse_result = jerry_parse (NULL,
0,
strict_equal_source,
sizeof (strict_equal_source) - 1,
JERRY_PARSE_STRICT_MODE);
TEST_ASSERT (!jerry_value_is_error (parse_result));
jerry_value_t strict_equal = jerry_run (parse_result);
TEST_ASSERT (!jerry_value_is_error (strict_equal));
jerry_release_value (parse_result);
jerry_value_t object = jerry_create_object ();
jerry_set_object_native_pointer (object, &test_data, &test_info);
jerry_value_t found_object;
TEST_ASSERT (jerry_objects_foreach_by_native_info (&test_info, find_test_object_by_data, &found_object));
jerry_value_t args[2] = {object, found_object};
jerry_value_t undefined = jerry_create_undefined ();
jerry_value_t strict_equal_result = jerry_call_function (strict_equal, undefined, args, 2);
TEST_ASSERT (jerry_value_is_boolean (strict_equal_result) && jerry_get_boolean_value (strict_equal_result));
jerry_release_value (strict_equal_result);
jerry_release_value (found_object);
jerry_release_value (object);
jerry_gc (JERRY_GC_PRESSURE_LOW);
TEST_ASSERT (!jerry_objects_foreach_by_native_info (&test_info, find_test_object_by_data, &found_object));
object = jerry_create_object ();
jerry_value_t property_name = jerry_create_string ((jerry_char_t *) "xyzzy");
jerry_value_t property_value = jerry_create_number (42);
jerry_release_value (jerry_set_property (object, property_name, property_value));
jerry_release_value (property_value);
args[0] = property_name;
TEST_ASSERT (jerry_objects_foreach (find_test_object_by_property, args));
args[0] = object;
strict_equal_result = jerry_call_function (strict_equal, undefined, args, 2);
TEST_ASSERT (jerry_value_is_boolean (strict_equal_result) && jerry_get_boolean_value (strict_equal_result));
jerry_release_value (strict_equal_result);
jerry_release_value (args[0]);
jerry_release_value (args[1]);
jerry_gc (JERRY_GC_PRESSURE_LOW);
args[0] = property_name;
TEST_ASSERT (!jerry_objects_foreach (find_test_object_by_property, args));
jerry_release_value (property_name);
jerry_release_value (undefined);
jerry_release_value (strict_equal);
test_container ();
test_internal_prop ();
jerry_cleanup ();
free (ctx_p);
}