- add sources.
[platform/framework/web/crosswalk.git] / src / content / renderer / cpp_bound_class_unittest.cc
1 // Copyright (c) 2012 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
5 // Tests for CppBoundClass, in conjunction with CppBindingExample.  Binds
6 // a CppBindingExample class into JavaScript in a custom test shell and tests
7 // the binding from the outside by loading JS into the shell.
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/public/common/url_constants.h"
11 #include "content/public/renderer/render_view_observer.h"
12 #include "content/public/test/render_view_test.h"
13 #include "content/test/cpp_binding_example.h"
14 #include "third_party/WebKit/public/platform/WebURLRequest.h"
15 #include "third_party/WebKit/public/web/WebDocument.h"
16 #include "third_party/WebKit/public/web/WebElement.h"
17
18 using webkit_glue::CppArgumentList;
19 using webkit_glue::CppVariant;
20
21 namespace content {
22
23 namespace {
24
25 class CppBindingExampleSubObject : public CppBindingExample {
26  public:
27   CppBindingExampleSubObject() {
28     sub_value_.Set("sub!");
29     BindProperty("sub_value", &sub_value_);
30   }
31  private:
32   CppVariant sub_value_;
33 };
34
35
36 class CppBindingExampleWithOptionalFallback : public CppBindingExample {
37  public:
38   CppBindingExampleWithOptionalFallback() {
39     BindProperty("sub_object", sub_object_.GetAsCppVariant());
40   }
41
42   void set_fallback_method_enabled(bool state) {
43     BindFallbackCallback(state ?
44         base::Bind(&CppBindingExampleWithOptionalFallback::fallbackMethod,
45                    base::Unretained(this))
46         : CppBoundClass::Callback());
47   }
48
49   // The fallback method does nothing, but because of it the JavaScript keeps
50   // running when a nonexistent method is called on an object.
51   void fallbackMethod(const CppArgumentList& args, CppVariant* result) {
52   }
53
54  private:
55   CppBindingExampleSubObject sub_object_;
56 };
57
58 class TestObserver : public RenderViewObserver {
59  public:
60   explicit TestObserver(RenderView* render_view)
61       : RenderViewObserver(render_view) {}
62   virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE {
63     example_bound_class_.BindToJavascript(frame, "example");
64   }
65   void set_fallback_method_enabled(bool use_fallback) {
66     example_bound_class_.set_fallback_method_enabled(use_fallback);
67   }
68  private:
69   CppBindingExampleWithOptionalFallback example_bound_class_;
70 };
71
72 }  // namespace
73
74 class CppBoundClassTest : public RenderViewTest {
75  public:
76   CppBoundClassTest() {}
77
78   virtual void SetUp() OVERRIDE {
79     RenderViewTest::SetUp();
80     observer_.reset(new TestObserver(view_));
81     observer_->set_fallback_method_enabled(useFallback());
82
83     WebKit::WebURLRequest url_request;
84     url_request.initialize();
85     url_request.setURL(GURL(kAboutBlankURL));
86
87     GetMainFrame()->loadRequest(url_request);
88     ProcessPendingMessages();
89   }
90
91   virtual void TearDown() OVERRIDE {
92     observer_.reset();
93     RenderViewTest::TearDown();
94   }
95
96   // Executes the specified JavaScript and checks that the resulting document
97   // text is empty.
98   void CheckJavaScriptFailure(const std::string& javascript) {
99     ExecuteJavaScript(javascript.c_str());
100     EXPECT_EQ(
101         "",
102         UTF16ToASCII(GetMainFrame()->document().documentElement().innerText()));
103   }
104
105   void CheckTrue(const std::string& expression) {
106     int was_page_a = -1;
107     string16 check_page_a =
108         ASCIIToUTF16(std::string("Number(") + expression + ")");
109     EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
110     EXPECT_EQ(1, was_page_a);
111   }
112
113  protected:
114   virtual bool useFallback() {
115     return false;
116   }
117
118  private:
119   scoped_ptr<TestObserver> observer_;
120 };
121
122 class CppBoundClassWithFallbackMethodTest : public CppBoundClassTest {
123  protected:
124   virtual bool useFallback() OVERRIDE {
125     return true;
126   }
127 };
128
129 // Ensures that the example object has been bound to JS.
130 TEST_F(CppBoundClassTest, ObjectExists) {
131   CheckTrue("typeof window.example == 'object'");
132
133   // An additional check to test our test.
134   CheckTrue("typeof window.invalid_object == 'undefined'");
135 }
136
137 TEST_F(CppBoundClassTest, PropertiesAreInitialized) {
138   CheckTrue("example.my_value == 10");
139
140   CheckTrue("example.my_other_value == 'Reinitialized!'");
141 }
142
143 TEST_F(CppBoundClassTest, SubOject) {
144   CheckTrue("typeof window.example.sub_object == 'object'");
145
146   CheckTrue("example.sub_object.sub_value == 'sub!'");
147 }
148
149 TEST_F(CppBoundClassTest, SetAndGetProperties) {
150   // The property on the left will be set to the value on the right, then
151   // checked to make sure it holds that same value.
152   static const std::string tests[] = {
153     "example.my_value", "7",
154     "example.my_value", "'test'",
155     "example.my_other_value", "3.14",
156     "example.my_other_value", "false",
157     "" // Array end marker: insert additional test pairs before this.
158   };
159
160   for (int i = 0; tests[i] != ""; i += 2) {
161     std::string left = tests[i];
162     std::string right = tests[i + 1];
163     // left = right;
164     std::string js = left;
165     js.append(" = ");
166     js.append(right);
167     js.append(";");
168     ExecuteJavaScript(js.c_str());
169     std::string expression = left;
170     expression += " == ";
171     expression += right;
172     CheckTrue(expression);
173   }
174 }
175
176 TEST_F(CppBoundClassTest, SetAndGetPropertiesWithCallbacks) {
177   // TODO(dglazkov): fix NPObject issues around failing property setters and
178   // getters and add tests for situations when GetProperty or SetProperty fail.
179   ExecuteJavaScript("example.my_value_with_callback = 10;");
180   CheckTrue("example.my_value_with_callback == 10");
181
182   ExecuteJavaScript("example.my_value_with_callback = 11;");
183   CheckTrue("example.my_value_with_callback == 11");
184
185   CheckTrue("example.same == 42");
186
187   ExecuteJavaScript("example.same = 24;");
188   CheckTrue("example.same == 42");
189 }
190
191 TEST_F(CppBoundClassTest, InvokeMethods) {
192   // The expression on the left is expected to return the value on the right.
193   static const std::string tests[] = {
194     "example.echoValue(true) == true",
195     "example.echoValue(13) == 13",
196     "example.echoValue(2.718) == 2.718",
197     "example.echoValue('yes') == 'yes'",
198     "example.echoValue() == null",     // Too few arguments
199
200     "example.echoType(false) == true",
201     "example.echoType(19) == 3.14159",
202     "example.echoType(9.876) == 3.14159",
203     "example.echoType('test string') == 'Success!'",
204     "example.echoType() == null",      // Too few arguments
205
206     // Comparing floats that aren't integer-valued is usually problematic due
207     // to rounding, but exact powers of 2 should also be safe.
208     "example.plus(2.5, 18.0) == 20.5",
209     "example.plus(2, 3.25) == 5.25",
210     "example.plus(2, 3) == 5",
211     "example.plus() == null",             // Too few arguments
212     "example.plus(1) == null",            // Too few arguments
213     "example.plus(1, 'test') == null",    // Wrong argument type
214     "example.plus('test', 2) == null",    // Wrong argument type
215     "example.plus('one', 'two') == null", // Wrong argument type
216     "" // Array end marker: insert additional test pairs before this.
217   };
218
219   for (int i = 0; tests[i] != ""; i++)
220     CheckTrue(tests[i]);
221
222   ExecuteJavaScript("example.my_value = 3.25; example.my_other_value = 1.25;");
223   CheckTrue("example.plus(example.my_value, example.my_other_value) == 4.5");
224 }
225
226 // Tests that invoking a nonexistent method with no fallback method stops the
227 // script's execution
228 TEST_F(CppBoundClassTest,
229        InvokeNonexistentMethodNoFallback) {
230   std::string js = "example.nonExistentMethod();document.writeln('SUCCESS');";
231   CheckJavaScriptFailure(js);
232 }
233
234 // Ensures existent methods can be invoked successfully when the fallback method
235 // is used
236 TEST_F(CppBoundClassWithFallbackMethodTest,
237        InvokeExistentMethodsWithFallback) {
238   CheckTrue("example.echoValue(34) == 34");
239 }
240
241 }  // namespace content