Chromium Code Reviews| Index: ios/web/web_state/ui/web_view_js_utils_unittest.mm |
| diff --git a/ios/web/web_state/ui/web_view_js_utils_unittest.mm b/ios/web/web_state/ui/web_view_js_utils_unittest.mm |
| index 50d6601ce13c281f6bf3eaca204bbdaa87db4f5a..dddb042186bc6f3b7b21d078d060a5f1da3c8667 100644 |
| --- a/ios/web/web_state/ui/web_view_js_utils_unittest.mm |
| +++ b/ios/web/web_state/ui/web_view_js_utils_unittest.mm |
| @@ -4,7 +4,9 @@ |
| #import "ios/web/web_state/ui/web_view_js_utils.h" |
| +#include "base/callback_helpers.h" |
| #include "base/logging.h" |
| +#include "base/mac/bind_objc_block.h" |
| #include "base/values.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| @@ -91,4 +93,42 @@ TEST(WebViewJsUtilsTest, ValueResultFromDictionaryWKResult) { |
| EXPECT_EQ(42, value3); |
| } |
| +// Tests that an NSDictionary with a cycle does not cause infinite recursion. |
| +TEST(WebViewJsUtilsTest, ValueResultFromDictionaryWithDepthCheckWKResult) { |
| + // Creates a dictionary with a cycle. |
|
Eugene But (OOO till 7-30)
2016/09/12 16:12:00
NIT: s/Creates/Create
We use imperative form for
jif
2016/09/13 09:41:10
Done. Thanks for the reminder :)
|
| + NSMutableDictionary* testDictionary = |
|
Eugene But (OOO till 7-30)
2016/09/12 16:12:00
s/testDictionary/test_dictionary
Also obj_c_key,
jif
2016/09/13 09:41:09
Done.
|
| + [NSMutableDictionary dictionaryWithCapacity:1]; |
| + NSMutableDictionary* testDictionary2 = |
| + [NSMutableDictionary dictionaryWithCapacity:1]; |
| + const char* key = "key"; |
| + NSString* objCKey = |
| + [NSString stringWithCString:key encoding:NSASCIIStringEncoding]; |
| + [testDictionary setObject:testDictionary2 forKey:objCKey]; |
|
Eugene But (OOO till 7-30)
2016/09/12 16:12:00
Do you want to use subscript?:
test_dictionary[o
jif
2016/09/13 09:41:09
Done.
|
| + [testDictionary2 setObject:testDictionary forKey:objCKey]; |
| + // Breaks the retain cycle so that the dictionaries are freed. |
| + base::ScopedClosureRunner runner(base::BindBlock(^{ |
| + [testDictionary2 removeAllObjects]; |
| + })); |
| + |
| + // Checks that parsing the dictionary stopped at a depth of |
| + // |kMaximumParsingRecursionDepth|. |
| + std::unique_ptr<base::Value> value = |
| + web::ValueResultFromWKResult(testDictionary); |
| + base::DictionaryValue* currentDictionary = nullptr; |
| + base::DictionaryValue* innerDictionary = nullptr; |
| + |
| + value->GetAsDictionary(¤tDictionary); |
| + EXPECT_NE(nullptr, currentDictionary); |
| + |
| + int currentDepth = 0; |
| + while (currentDepth <= kMaximumParsingRecursionDepth) { |
|
Eugene But (OOO till 7-30)
2016/09/12 16:12:00
Should this be a for loop?:
for (int current_depth
Eugene But (OOO till 7-30)
2016/09/12 16:12:00
How about using very large number instead of kMaxi
jif
2016/09/13 09:41:09
If someone changes kMaximumParsingRecursionDepth t
jif
2016/09/13 09:41:10
Done.
|
| + EXPECT_NE(nullptr, currentDictionary); |
| + innerDictionary = nullptr; |
| + currentDictionary->GetDictionary(key, &innerDictionary); |
| + currentDictionary = innerDictionary; |
| + currentDepth++; |
| + } |
| + EXPECT_EQ(nullptr, currentDictionary); |
| +} |
| + |
| } // namespace web |