Feature #11599 » objspace_dump_hash_entries.patch
ChangeLog | ||
---|---|---|
merging load_file_internal and load_file_internal2, and remove
|
||
nested rb_protect and rb_ensure.
|
||
Sat Oct 17 08:47:41 2015 Yosi Attias <yosy101@gmail.com>
|
||
* ext/objspace/objspace_dump.c(dump_object): Dump entries of hash - the key & values.
|
||
* test/objspace/test_objspace.rb: Adding test for the entires - test_dump_entries_empty_hash and test_dump_entries_hash
|
||
Sat Oct 17 05:28:32 2015 Rei Odaira <Rei.Odaira@gmail.com>
|
||
* test/ruby/test_symbol.rb (test_symbol_fstr_leak): add a warm-up
|
ext/objspace/objspace_dump.c | ||
---|---|---|
return "UNKNOWN";
|
||
}
|
||
struct hash_keys_iter {
|
||
struct dump_config *dc;
|
||
int cur_i;
|
||
};
|
||
static void
|
||
dump_hash_value(struct dump_config *dc, VALUE value, const char *prefix) {
|
||
dump_append(dc, "\"is_%s_address\": %s,", prefix, SPECIAL_CONST_P(value) ? "false" : "true");
|
||
dump_append(dc, "\"%s\":", prefix);
|
||
if(!SPECIAL_CONST_P(value)) {
|
||
dump_append(dc, "\"%p\"", (void *)value);
|
||
} else {
|
||
dump_append_string_value(dc, rb_inspect(value));
|
||
}
|
||
}
|
||
static int
|
||
hash_entries_iter(VALUE key, VALUE value, VALUE arg)
|
||
{
|
||
struct hash_keys_iter *keys_iter = (struct hash_keys_iter *)arg;
|
||
if(keys_iter->cur_i > 0) {
|
||
dump_append(keys_iter->dc, ",");
|
||
}
|
||
dump_append(keys_iter->dc, "{");
|
||
dump_hash_value(keys_iter->dc, key, "key");
|
||
dump_append(keys_iter->dc, ",");
|
||
dump_hash_value(keys_iter->dc, value, "value");
|
||
dump_append(keys_iter->dc, "}");
|
||
keys_iter->cur_i++;
|
||
return ST_CONTINUE;
|
||
}
|
||
static void
|
||
dump_hash_entries(struct dump_config *dc, VALUE hash) {
|
||
if(RHASH_SIZE(hash) == 0) {
|
||
dump_append(dc, ", \"entries\": []");
|
||
} else {
|
||
struct hash_keys_iter arg;
|
||
arg.dc = dc;
|
||
arg.cur_i = 0;
|
||
dump_append(dc, ", \"entries\": [");
|
||
rb_hash_foreach(hash, hash_entries_iter, (VALUE)&arg);
|
||
dump_append(dc, "]");
|
||
}
|
||
}
|
||
static void
|
||
reachable_object_i(VALUE ref, void *data)
|
||
{
|
||
... | ... | |
case T_HASH:
|
||
dump_append(dc, ", \"size\":%ld", RHASH_SIZE(obj));
|
||
dump_hash_entries(dc, obj);
|
||
if (FL_TEST(obj, HASH_PROC_DEFAULT))
|
||
dump_append(dc, ", \"default\":\"%p\"", (void *)RHASH_IFNONE(obj));
|
||
break;
|
test/objspace/test_objspace.rb | ||
---|---|---|
require "test/unit"
|
||
require "objspace"
|
||
require "json"
|
||
class TestObjSpace < Test::Unit::TestCase
|
||
def test_memsize_of
|
||
... | ... | |
assert_match /"method":"#{loc.base_label}"/, info
|
||
end
|
||
def test_dump_entries_empty_hash
|
||
dumped_hash = JSON.parse(ObjectSpace.dump({}))
|
||
assert_equal [], dumped_hash["entries"]
|
||
end
|
||
def test_dump_entries_hash
|
||
# freeze the string, so we will use the same string in the hash..
|
||
str_key = "Hello world".freeze
|
||
hash = {}
|
||
hash[:a] = 1
|
||
hash[str_key] = -1
|
||
str_key_d = JSON.parse(ObjectSpace.dump(str_key))
|
||
dumped_hash = JSON.parse(ObjectSpace.dump(hash))
|
||
# make sure we have two entries
|
||
assert_equal 2, dumped_hash["entries"].length
|
||
# check the first entry
|
||
first_entry = dumped_hash["entries"][0]
|
||
assert_equal false, first_entry["is_key_address"]
|
||
assert_equal ":a", first_entry["key"]
|
||
assert_equal false, first_entry["is_value_address"]
|
||
assert_equal "1", first_entry["value"]
|
||
# check the second entry
|
||
second_entry = dumped_hash["entries"][1]
|
||
assert_equal true, second_entry["is_key_address"]
|
||
assert_equal str_key_d["address"], second_entry["key"]
|
||
assert_equal false, second_entry["is_value_address"]
|
||
assert_equal "-1", second_entry["value"]
|
||
end
|
||
def test_dump_special_consts
|
||
# [ruby-core:69692] [Bug #11291]
|
||
assert_equal('{}', ObjectSpace.dump(nil))
|