1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests for CppBoundClass, in conjunction with CppBindingExample.  Binds
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a CppBindingExample class into JavaScript in a custom test shell and tests
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the binding from the outside by loading JS into the shell.
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/string_util.h"
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/cpp_binding_example.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/webkit_glue.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/tools/test_shell/test_shell_test.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebFrame;
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CppBindingExampleSubObject : public CppBindingExample {
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CppBindingExampleSubObject() {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sub_value_.Set("sub!");
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BindProperty("sub_value", &sub_value_);
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CppVariant sub_value_;
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CppBindingExampleWithOptionalFallback : public CppBindingExample {
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CppBindingExampleWithOptionalFallback() {
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BindProperty("sub_object", sub_object_.GetAsCppVariant());
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void set_fallback_method_enabled(bool state) {
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BindFallbackMethod(state ?
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        &CppBindingExampleWithOptionalFallback::fallbackMethod
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        : NULL);
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The fallback method does nothing, but because of it the JavaScript keeps
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // running when a nonexistent method is called on an object.
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void fallbackMethod(const CppArgumentList& args, CppVariant* result) {
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CppBindingExampleSubObject sub_object_;
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ExampleTestShell : public TestShell {
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExampleTestShell(bool use_fallback_method) {
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    example_bound_class_.set_fallback_method_enabled(use_fallback_method);
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When called by WebViewDelegate::WindowObjectCleared method, this binds a
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // CppExampleObject to window.example.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void BindJSObjectsToWindow(WebFrame* frame) {
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    example_bound_class_.BindToJavascript(frame, "example");
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We use the layoutTestController binding for notifyDone.
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestShell::BindJSObjectsToWindow(frame);
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is a public interface to TestShell's protected method, so it
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // can be called by our CreateEmptyWindow.
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool PublicInitialize(const std::string& starting_url) {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return Initialize(GURL(starting_url));
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CppBindingExampleWithOptionalFallback example_bound_class_;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CppBoundClassTest : public TestShellTest {
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // Adapted from TestShell::CreateNewWindow, this creates an
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // ExampleTestShellWindow rather than a regular TestShell.
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   virtual void CreateEmptyWindow() {
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     ExampleTestShell* host = new ExampleTestShell(useFallback());
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     ASSERT_TRUE(host != NULL);
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     bool rv = host->PublicInitialize("about:blank");
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     if (rv) {
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       test_shell_ = host;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       TestShell::windowList()->push_back(host->mainWnd());
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       webframe_ = test_shell_->webView()->mainFrame();
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       ASSERT_TRUE(webframe_ != NULL);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     } else {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       delete host;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     }
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   }
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // Wraps the given JavaScript snippet in <html><body><script> tags, then
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // loads it into a webframe so it is executed.
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   void ExecuteJavaScript(const std::string& javascript) {
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     std::string html = "<html><body>";
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     html.append(TestShellTest::kJavascriptDelayExitScript);
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     html.append("<script>");
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     html.append(javascript);
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     html.append("</script></body></html>");
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     // The base URL doesn't matter.
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     webframe_->loadHTMLString(html, GURL("about:blank"));
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     test_shell_->WaitTestFinished();
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // Executes the specified JavaScript and checks to be sure that the resulting
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // document text is exactly "SUCCESS".
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   void CheckJavaScriptSuccess(const std::string& javascript) {
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     ExecuteJavaScript(javascript);
11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     EXPECT_EQ("SUCCESS",
11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen               UTF16ToASCII(webkit_glue::DumpDocumentText(webframe_)));
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   }
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // Executes the specified JavaScript and checks that the resulting document
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // text is empty.
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   void CheckJavaScriptFailure(const std::string& javascript) {
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     ExecuteJavaScript(javascript);
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     EXPECT_EQ("", UTF16ToASCII(webkit_glue::DumpDocumentText(webframe_)));
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   }
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // Constructs a JavaScript snippet that evaluates and compares the left and
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // right expressions, printing "SUCCESS" to the page if they are equal and
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // printing their actual values if they are not.  Any strings in the
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // expressions should be enclosed in single quotes, and no double quotes
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // should appear in either expression (even if escaped). (If a test case
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // is added that needs fancier quoting, Json::valueToQuotedString could be
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   // used here.  For now, it's not worth adding the dependency.)
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   std::string BuildJSCondition(std::string left, std::string right) {
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     return "var leftval = " + left + ";" +
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            "var rightval = " + right + ";" +
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            "if (leftval == rightval) {" +
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            "  document.writeln('SUCCESS');" +
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            "} else {" +
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            "  document.writeln(\"" +
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 left + " [\" + leftval + \"] != " +
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 right + " [\" + rightval + \"]\");" +
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            "}";
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   }
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochprotected:
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool useFallback() {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochprivate:
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebFrame* webframe_;
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CppBoundClassWithFallbackMethodTest : public CppBoundClassTest {
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochprotected:
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool useFallback() {
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Ensures that the example object has been bound to JS.
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(CppBoundClassTest, ObjectExists) {
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string js = BuildJSCondition("typeof window.example", "'object'");
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptSuccess(js);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // An additional check to test our test.
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  js = BuildJSCondition("typeof window.invalid_object", "'undefined'");
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptSuccess(js);
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(CppBoundClassTest, PropertiesAreInitialized) {
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string js = BuildJSCondition("example.my_value", "10");
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptSuccess(js);
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  js = BuildJSCondition("example.my_other_value", "'Reinitialized!'");
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptSuccess(js);
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(CppBoundClassTest, SubOject) {
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string js = BuildJSCondition("typeof window.example.sub_object",
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    "'object'");
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptSuccess(js);
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  js = BuildJSCondition("example.sub_object.sub_value", "'sub!'");
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptSuccess(js);
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(CppBoundClassTest, SetAndGetProperties) {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The property on the left will be set to the value on the right, then
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // checked to make sure it holds that same value.
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const std::string tests[] = {
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.my_value", "7",
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.my_value", "'test'",
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.my_other_value", "3.14",
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.my_other_value", "false",
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "" // Array end marker: insert additional test pairs before this.
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; tests[i] != ""; i += 2) {
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string left = tests[i];
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string right = tests[i + 1];
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // left = right;
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string js = left;
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    js.append(" = ");
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    js.append(right);
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    js.append(";");
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    js.append(BuildJSCondition(left, right));
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CheckJavaScriptSuccess(js);
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(CppBoundClassTest, SetAndGetPropertiesWithCallbacks) {
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(dglazkov): fix NPObject issues around failing property setters and
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // getters and add tests for situations when GetProperty or SetProperty fail.
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string js = "var result = 'SUCCESS';\n"
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.my_value_with_callback = 10;\n"
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "if (example.my_value_with_callback != 10)\n"
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "  result = 'FAIL: unable to set property.';\n"
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.my_value_with_callback = 11;\n"
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "if (example.my_value_with_callback != 11)\n"
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "  result = 'FAIL: unable to set property again';\n"
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "if (example.same != 42)\n"
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "  result = 'FAIL: same property should always be 42';\n"
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.same = 24;\n"
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "if (example.same != 42)\n"
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "  result = 'FAIL: same property should always be 42';\n"
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "document.writeln(result);\n";
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptSuccess(js);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(CppBoundClassTest, InvokeMethods) {
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The expression on the left is expected to return the value on the right.
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const std::string tests[] = {
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.echoValue(true)", "true",
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.echoValue(13)", "13",
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.echoValue(2.718)", "2.718",
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.echoValue('yes')", "'yes'",
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.echoValue()", "null",     // Too few arguments
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.echoType(false)", "true",
24321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    "example.echoType(19)", "3.14159",
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.echoType(9.876)", "3.14159",
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.echoType('test string')", "'Success!'",
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.echoType()", "null",      // Too few arguments
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Comparing floats that aren't integer-valued is usually problematic due
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // to rounding, but exact powers of 2 should also be safe.
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.plus(2.5, 18.0)", "20.5",
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.plus(2, 3.25)", "5.25",
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.plus(2, 3)", "5",
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.plus()", "null",             // Too few arguments
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.plus(1)", "null",            // Too few arguments
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.plus(1, 'test')", "null",    // Wrong argument type
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.plus('test', 2)", "null",    // Wrong argument type
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "example.plus('one', 'two')", "null", // Wrong argument type
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "" // Array end marker: insert additional test pairs before this.
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; tests[i] != ""; i+= 2) {
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string left = tests[i];
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string right = tests[i + 1];
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string js = BuildJSCondition(left, right);
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CheckJavaScriptSuccess(js);
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string js = "example.my_value = 3.25; example.my_other_value = 1.25;";
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  js.append(BuildJSCondition(
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "example.plus(example.my_value, example.my_other_value)", "4.5"));
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptSuccess(js);
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests that invoking a nonexistent method with no fallback method stops the
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// script's execution
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(CppBoundClassTest,
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       InvokeNonexistentMethodNoFallback) {
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string js = "example.nonExistentMethod();document.writeln('SUCCESS');";
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptFailure(js);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Ensures existent methods can be invoked successfully when the fallback method
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is used
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(CppBoundClassWithFallbackMethodTest,
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       InvokeExistentMethodsWithFallback) {
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string js = BuildJSCondition("example.echoValue(34)", "34");
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CheckJavaScriptSuccess(js);
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
291