blob: e80d8591586ae5ac381f1b860c0d1e695d2c9d76 [file] [log] [blame]
/*
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cobalt/bindings/testing/base_interface.h"
#include "cobalt/bindings/testing/bindings_test_base.h"
#include "cobalt/bindings/testing/derived_interface.h"
#include "cobalt/bindings/testing/object_type_bindings_interface.h"
#include "cobalt/bindings/testing/script_object_owner.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::StartsWith;
using ::testing::StrictMock;
namespace cobalt {
namespace bindings {
namespace testing {
namespace {
class PlatformObjectBindingsTest
: public InterfaceBindingsTest<ObjectTypeBindingsInterface> {
public:
PlatformObjectBindingsTest()
: arbitrary_interface_(new StrictMock<ArbitraryInterface>()),
base_interface_(new StrictMock<BaseInterface>()),
derived_interface_(new StrictMock<DerivedInterface>()) {
ON_CALL(test_mock(), arbitrary_object())
.WillByDefault(Return(arbitrary_interface_));
ON_CALL(test_mock(), base_interface())
.WillByDefault(Return(base_interface_));
ON_CALL(test_mock(), derived_interface())
.WillByDefault(Return(derived_interface_));
}
protected:
const scoped_refptr<ArbitraryInterface> arbitrary_interface_;
const scoped_refptr<BaseInterface> base_interface_;
const scoped_refptr<DerivedInterface> derived_interface_;
};
class UserObjectBindingsTest
: public InterfaceBindingsTest<ObjectTypeBindingsInterface> {
public:
UserObjectBindingsTest()
: arbitrary_interface_(new StrictMock<ArbitraryInterface>()) {
ON_CALL(test_mock(), arbitrary_object())
.WillByDefault(Return(arbitrary_interface_));
}
protected:
const scoped_refptr<ArbitraryInterface> arbitrary_interface_;
};
} // namespace
TEST_F(PlatformObjectBindingsTest, InstanceOfObject) {
EXPECT_CALL(test_mock(), arbitrary_object());
std::string result;
EXPECT_TRUE(
EvaluateScript("test.arbitraryObject instanceof Object;", &result));
EXPECT_STREQ("true", result.c_str());
}
TEST_F(PlatformObjectBindingsTest, Prototype) {
EXPECT_CALL(test_mock(), arbitrary_object());
std::string result;
EXPECT_TRUE(
EvaluateScript("Object.getPrototypeOf(test.arbitraryObject);", &result));
EXPECT_STREQ("[object ArbitraryInterfacePrototype]", result.c_str());
}
#if defined(ENGINE_DEFINES_ATTRIBUTES_ON_OBJECT)
TEST_F(PlatformObjectBindingsTest, PropertyIsOwnProperty) {
EXPECT_CALL(test_mock(), arbitrary_object());
std::string result;
EXPECT_TRUE(EvaluateScript(
"test.arbitraryObject.hasOwnProperty(\"arbitraryProperty\");", &result));
EXPECT_STREQ("true", result.c_str());
}
#else
TEST_F(PlatformObjectBindingsTest, PropertyIsDefinedOnPrototype) {
EXPECT_CALL(test_mock(), arbitrary_object());
std::string result;
EXPECT_TRUE(EvaluateScript(
"Object.getPrototypeOf(test.arbitraryObject).hasOwnProperty("
"\"arbitraryProperty\");",
&result));
EXPECT_STREQ("true", result.c_str());
}
#endif // defined(ENGINE_DEFINES_ATTRIBUTES_ON_OBJECT)
TEST_F(PlatformObjectBindingsTest, MemberFunctionIsPrototypeProperty) {
EXPECT_CALL(test_mock(), arbitrary_object()).Times(3);
std::string result;
EXPECT_TRUE(EvaluateScript(
"test.arbitraryObject.hasOwnProperty(\"arbitraryFunction\");", &result));
EXPECT_STREQ("false", result.c_str());
EXPECT_TRUE(EvaluateScript(
"Object.getPrototypeOf(test.arbitraryObject).hasOwnProperty("
"\"arbitraryFunction\");",
&result));
EXPECT_STREQ("true", result.c_str());
EXPECT_TRUE(EvaluateScript("\"arbitraryFunction\" in test.arbitraryObject;",
&result));
EXPECT_STREQ("true", result.c_str());
}
TEST_F(PlatformObjectBindingsTest, DerivedProto) {
EXPECT_CALL(test_mock(), derived_interface());
std::string result;
EXPECT_TRUE(EvaluateScript(
"Object.getPrototypeOf(test.derivedInterface) === "
"DerivedInterface.prototype;",
&result));
EXPECT_STREQ("true", result.c_str());
}
TEST_F(PlatformObjectBindingsTest, PropertyOnBaseClass) {
EXPECT_CALL(test_mock(), derived_interface());
EXPECT_CALL(*derived_interface_, base_attribute())
.WillOnce(Return("mock_value"));
std::string result;
EXPECT_TRUE(EvaluateScript("test.derivedInterface.baseAttribute;", &result));
EXPECT_STREQ("mock_value", result.c_str());
}
TEST_F(PlatformObjectBindingsTest, OperationOnBaseClass) {
EXPECT_CALL(test_mock(), derived_interface());
EXPECT_CALL(*derived_interface_, BaseOperation());
EXPECT_TRUE(EvaluateScript("test.derivedInterface.baseOperation();", NULL));
}
TEST_F(PlatformObjectBindingsTest, PropertyOnDerivedClass) {
EXPECT_CALL(test_mock(), derived_interface());
EXPECT_CALL(*derived_interface_, derived_attribute())
.WillOnce(Return("mock_value"));
std::string result;
EXPECT_TRUE(
EvaluateScript("test.derivedInterface.derivedAttribute;", &result));
EXPECT_STREQ("mock_value", result.c_str());
}
TEST_F(PlatformObjectBindingsTest, OperationOnDerivedClass) {
EXPECT_CALL(test_mock(), derived_interface());
EXPECT_CALL(*derived_interface_, DerivedOperation());
EXPECT_TRUE(
EvaluateScript("test.derivedInterface.derivedOperation();", NULL));
}
TEST_F(PlatformObjectBindingsTest, ReturnDerivedClassWrapper) {
ON_CALL(test_mock(), base_interface())
.WillByDefault(Return(derived_interface_));
std::string result;
EXPECT_CALL(test_mock(), base_interface());
EXPECT_TRUE(
EvaluateScript("Object.getPrototypeOf(test.baseInterface);", &result));
EXPECT_STREQ("[object DerivedInterfacePrototype]", result.c_str());
EXPECT_CALL(test_mock(), base_interface());
EXPECT_CALL(*derived_interface_, DerivedOperation());
EXPECT_TRUE(EvaluateScript("test.baseInterface.derivedOperation();", NULL));
}
TEST_F(PlatformObjectBindingsTest, ReturnCorrectWrapperForObjectType) {
typedef ScriptObjectOwner<script::OpaqueHandleHolder> ObjectOwner;
ObjectOwner object_owner(&test_mock());
// Store the Wrappable object as an opaque handle.
EXPECT_CALL(test_mock(), set_object_property(_))
.WillOnce(Invoke(&object_owner, &ObjectOwner::TakeOwnership));
EXPECT_TRUE(
EvaluateScript("test.objectProperty = new ArbitraryInterface();", NULL));
ASSERT_TRUE(object_owner.IsSet());
// Return it back to JS as the original type.
EXPECT_CALL(test_mock(), object_property())
.WillOnce(Return(&object_owner.reference().referenced_object()));
EXPECT_TRUE(
EvaluateScript("Object.getPrototypeOf(test.objectProperty) === "
"ArbitraryInterface.prototype;",
NULL));
}
TEST_F(UserObjectBindingsTest, PassUserObjectforObjectType) {
typedef ScriptObjectOwner<script::OpaqueHandleHolder> ObjectOwner;
ObjectOwner object_owner(&test_mock());
EXPECT_TRUE(EvaluateScript("var obj = new Object();", NULL));
EXPECT_CALL(test_mock(), set_object_property(_))
.WillOnce(Invoke(&object_owner, &ObjectOwner::TakeOwnership));
EXPECT_TRUE(EvaluateScript("test.objectProperty = obj;", NULL));
ASSERT_TRUE(object_owner.IsSet());
EXPECT_CALL(test_mock(), object_property())
.WillOnce(Return(&object_owner.reference().referenced_object()));
EXPECT_TRUE(EvaluateScript("test.objectProperty === obj;", NULL));
}
TEST_F(UserObjectBindingsTest, NullObject) {
typedef ScriptObjectOwner<script::OpaqueHandleHolder> ObjectOwner;
ObjectOwner object_owner(&test_mock());
EXPECT_CALL(test_mock(), set_object_property(_))
.WillOnce(Invoke(&object_owner, &ObjectOwner::TakeOwnership));
EXPECT_TRUE(EvaluateScript("test.objectProperty = null;", NULL));
EXPECT_FALSE(object_owner.IsSet());
EXPECT_CALL(test_mock(), object_property());
EXPECT_TRUE(EvaluateScript("test.objectProperty === null;", NULL));
}
TEST_F(UserObjectBindingsTest, NonObjectType) {
std::string result;
EXPECT_FALSE(EvaluateScript("test.objectProperty = 5;", &result));
EXPECT_THAT(result.c_str(), StartsWith("TypeError:"));
EXPECT_FALSE(EvaluateScript("test.objectProperty = false;", &result));
EXPECT_THAT(result.c_str(), StartsWith("TypeError:"));
EXPECT_FALSE(EvaluateScript("test.objectProperty = \"string\";", &result));
EXPECT_THAT(result.c_str(), StartsWith("TypeError:"));
EXPECT_FALSE(EvaluateScript("test.objectProperty = undefined;", &result));
EXPECT_THAT(result.c_str(), StartsWith("TypeError:"));
}
TEST_F(UserObjectBindingsTest, SetNonObject) {
std::string result;
EXPECT_FALSE(EvaluateScript("test.objectProperty = 5", &result));
EXPECT_THAT(result.c_str(), StartsWith("TypeError:"));
}
TEST_F(UserObjectBindingsTest, SetUndefinedObject) {
std::string result;
EXPECT_FALSE(EvaluateScript("test.arbitraryObject = undefined;", &result));
EXPECT_THAT(result.c_str(), StartsWith("TypeError:"));
}
TEST_F(UserObjectBindingsTest, SetWrongObjectType) {
std::string result;
EXPECT_FALSE(EvaluateScript("test.arbitraryObject = new Object()", &result));
EXPECT_THAT(result.c_str(), StartsWith("TypeError:"));
EXPECT_FALSE(
EvaluateScript("test.derivedInterface = new BaseInterface()", &result));
EXPECT_THAT(result.c_str(), StartsWith("TypeError:"));
}
TEST_F(UserObjectBindingsTest, CallWrongObjectType) {
std::string result;
EXPECT_TRUE(EvaluateScript("var obj = new Object()", NULL));
EXPECT_TRUE(EvaluateScript("var arb = new ArbitraryInterface()", NULL));
// Calling a function with the wrong object type is a type error.
EXPECT_FALSE(
EvaluateScript("obj.arbitraryFunction = arb.arbitraryFunction;\n"
"obj.arbitraryFunction();", &result));
EXPECT_THAT(result.c_str(), StartsWith("TypeError:"));
}
} // namespace testing
} // namespace bindings
} // namespace cobalt