blob: 851a4561d167cef7409abcd6ad95fcbb12b4562d [file] [log] [blame]
bauerb4c2863e2015-01-06 00:26:301// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
dcheng4af48582016-04-19 00:29:355#include <memory>
6
bauerb4c2863e2015-01-06 00:26:307#include "base/bind.h"
8#include "base/json/json_reader.h"
9#include "base/json/json_writer.h"
Gabriel Charetteb164afef2017-11-21 20:59:3110#include "base/run_loop.h"
bauerb4c2863e2015-01-06 00:26:3011#include "base/values.h"
bauerb4c2863e2015-01-06 00:26:3012#include "chrome/test/base/in_process_browser_test.h"
Jay Civelli90a4cb12017-11-28 21:04:5213#include "chrome/test/base/test_service_manager_listener.h"
Jay Civelliab99a9c2017-10-13 17:48:2314#include "content/public/common/service_manager_connection.h"
bauerb4c2863e2015-01-06 00:26:3015#include "content/public/test/test_browser_thread_bundle.h"
16#include "content/public/test/test_utils.h"
Jay Civelliab99a9c2017-10-13 17:48:2317#include "services/data_decoder/public/cpp/safe_json_parser.h"
Ken Rockot19db6382018-02-10 01:41:0218#include "services/data_decoder/public/mojom/constants.mojom.h"
19#include "services/data_decoder/public/mojom/json_parser.mojom.h"
Jay Civellid8dc7c62017-11-02 02:10:4120#include "services/service_manager/public/cpp/connector.h"
Ken Rockot543f5e32018-02-04 02:13:5021#include "services/service_manager/public/mojom/service_manager.mojom.h"
bauerb4c2863e2015-01-06 00:26:3022
23namespace {
24
Jay Civelliab99a9c2017-10-13 17:48:2325using data_decoder::SafeJsonParser;
eranmb7951552015-06-03 08:38:1326
bauerb4c2863e2015-01-06 00:26:3027std::string MaybeToJson(const base::Value* value) {
28 if (!value)
29 return "(null)";
30
31 std::string json;
estade8d046462015-05-16 01:02:3432 if (!base::JSONWriter::Write(*value, &json))
bauerb4c2863e2015-01-06 00:26:3033 return "(invalid value)";
34
35 return json;
36}
37
Jay Civellid8dc7c62017-11-02 02:10:4138class ParseCallback {
39 public:
40 explicit ParseCallback(base::Closure callback) : callback_(callback) {}
41
42 void OnSuccess(std::unique_ptr<base::Value> value) {
43 success_ = true;
44 callback_.Run();
45 }
46
47 void OnError(const std::string& error) {
48 success_ = false;
49 callback_.Run();
50 }
51
52 bool success() const { return success_; }
53
54 private:
55 bool success_ = false;
56 base::Closure callback_;
57
58 DISALLOW_COPY_AND_ASSIGN(ParseCallback);
59};
Jay Civellid8dc7c62017-11-02 02:10:4160
bauerb4c2863e2015-01-06 00:26:3061class SafeJsonParserTest : public InProcessBrowserTest {
62 protected:
63 void TestParse(const std::string& json) {
64 SCOPED_TRACE(json);
65 DCHECK(!message_loop_runner_);
66 message_loop_runner_ = new content::MessageLoopRunner;
67
68 std::string error;
dcheng4af48582016-04-19 00:29:3569 std::unique_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
estadeb09312b2015-05-22 16:30:1370 json, base::JSON_PARSE_RFC, nullptr, &error);
bauerb4c2863e2015-01-06 00:26:3071
72 SafeJsonParser::SuccessCallback success_callback;
73 SafeJsonParser::ErrorCallback error_callback;
74 if (value) {
75 success_callback =
76 base::Bind(&SafeJsonParserTest::ExpectValue, base::Unretained(this),
77 base::Passed(&value));
78 error_callback = base::Bind(&SafeJsonParserTest::FailWithError,
79 base::Unretained(this));
80 } else {
81 success_callback = base::Bind(&SafeJsonParserTest::FailWithValue,
82 base::Unretained(this));
83 error_callback = base::Bind(&SafeJsonParserTest::ExpectError,
84 base::Unretained(this), error);
85 }
Jay Civelliab99a9c2017-10-13 17:48:2386 SafeJsonParser::Parse(
87 content::ServiceManagerConnection::GetForProcess()->GetConnector(),
88 json, success_callback, error_callback);
bauerb4c2863e2015-01-06 00:26:3089
90 message_loop_runner_->Run();
91 message_loop_runner_ = nullptr;
92 }
93
94 private:
dcheng4af48582016-04-19 00:29:3595 void ExpectValue(std::unique_ptr<base::Value> expected_value,
96 std::unique_ptr<base::Value> actual_value) {
jdoerrie8551f922017-07-25 10:55:1397 EXPECT_EQ(*expected_value, *actual_value)
bauerb4c2863e2015-01-06 00:26:3098 << "Expected: " << MaybeToJson(expected_value.get())
99 << " Actual: " << MaybeToJson(actual_value.get());
100 message_loop_runner_->Quit();
101 }
102
103 void ExpectError(const std::string& expected_error,
104 const std::string& actual_error) {
105 EXPECT_EQ(expected_error, actual_error);
106 message_loop_runner_->Quit();
107 }
108
dcheng4af48582016-04-19 00:29:35109 void FailWithValue(std::unique_ptr<base::Value> value) {
bauerb4c2863e2015-01-06 00:26:30110 ADD_FAILURE() << MaybeToJson(value.get());
111 message_loop_runner_->Quit();
112 }
113
114 void FailWithError(const std::string& error) {
115 ADD_FAILURE() << error;
116 message_loop_runner_->Quit();
117 }
118
119 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
120};
121
Jay Civellid8dc7c62017-11-02 02:10:41122class SafeJsonParserImplTest : public InProcessBrowserTest {
123 public:
124 SafeJsonParserImplTest() = default;
125
126 protected:
127 // InProcessBrowserTest implementation:
128 void SetUpOnMainThread() override {
129 InProcessBrowserTest::SetUpOnMainThread();
130
Jay Civelli90a4cb12017-11-28 21:04:52131 // Initialize the TestServiceManagerListener so it starts listening for
132 // service activity.
133 listener_.Init();
Jay Civellid8dc7c62017-11-02 02:10:41134
135 // The data_decoder service will stop if no connection is bound to it after
136 // 5 seconds. We bind a connection to it for the duration of the test so it
137 // is guaranteed the service is always running.
Jay Civelli90a4cb12017-11-28 21:04:52138 connector()->BindInterface(data_decoder::mojom::kServiceName,
139 &json_parser_ptr_);
Jay Civellid8dc7c62017-11-02 02:10:41140 listener_.WaitUntilServiceStarted(data_decoder::mojom::kServiceName);
141 EXPECT_EQ(
142 1U, listener_.GetServiceStartCount(data_decoder::mojom::kServiceName));
143 }
144
Jay Civelli90a4cb12017-11-28 21:04:52145 service_manager::Connector* connector() const {
146 return content::ServiceManagerConnection::GetForProcess()->GetConnector();
147 }
Jay Civellid8dc7c62017-11-02 02:10:41148
149 uint32_t GetServiceStartCount(const std::string& service_name) const {
150 return listener_.GetServiceStartCount(service_name);
151 }
152
153 private:
154 data_decoder::mojom::JsonParserPtr json_parser_ptr_;
Jay Civellid8dc7c62017-11-02 02:10:41155 TestServiceManagerListener listener_;
Jay Civellid8dc7c62017-11-02 02:10:41156
157 DISALLOW_COPY_AND_ASSIGN(SafeJsonParserImplTest);
158};
Jay Civellid8dc7c62017-11-02 02:10:41159
Jay Civelli90a4cb12017-11-28 21:04:52160} // namespace
161
Jay Civelliab99a9c2017-10-13 17:48:23162IN_PROC_BROWSER_TEST_F(SafeJsonParserTest, Parse) {
bauerb4c2863e2015-01-06 00:26:30163 TestParse("{}");
164 TestParse("choke");
165 TestParse("{\"awesome\": true}");
166 TestParse("\"laser\"");
167 TestParse("false");
168 TestParse("null");
169 TestParse("3.14");
170 TestParse("[");
171 TestParse("\"");
172 TestParse(std::string());
173 TestParse("☃");
174 TestParse("\"☃\"");
bauerbd7de09a2015-07-02 16:20:44175 TestParse("\"\\ufdd0\"");
176 TestParse("\"\\ufffe\"");
177 TestParse("\"\\ud83f\\udffe\"");
bauerb4c2863e2015-01-06 00:26:30178}
Jay Civellid8dc7c62017-11-02 02:10:41179
Jay Civellid8dc7c62017-11-02 02:10:41180// Tests that when calling SafeJsonParser::Parse() a new service is started
181// every time.
182IN_PROC_BROWSER_TEST_F(SafeJsonParserImplTest, Isolation) {
183 for (int i = 0; i < 5; i++) {
184 base::RunLoop run_loop;
185 ParseCallback parse_callback(run_loop.QuitClosure());
186 SafeJsonParser::Parse(
187 connector(), "[\"awesome\", \"possum\"]",
188 base::Bind(&ParseCallback::OnSuccess,
189 base::Unretained(&parse_callback)),
190 base::Bind(&ParseCallback::OnError, base::Unretained(&parse_callback)));
191 run_loop.Run();
192 EXPECT_TRUE(parse_callback.success());
193 // 2 + i below because the data_decoder is already running and the index
194 // starts at 0.
195 EXPECT_EQ(2U + i, GetServiceStartCount(data_decoder::mojom::kServiceName));
196 }
197}