KAGUYA_TEST_FUNCTION_DEF(object_take_copy)(kaguya::State& state)
{
	state["Base"].setClass(kaguya::ClassMetatable<Base>()
		.addConstructor()
		.addProperty("a", &Base::a)
		);

	TEST_CHECK(state("fn = function(object,value) object.a = value end"));
	{
		Base base;
		base.a = 232;
		state["obj"] = base;
		TEST_CHECK(state("assert(obj.a==232)"));
		TEST_CHECK(state("obj.a = 2"));
		TEST_CHECK(state("assert(obj.a==2)"));
		TEST_EQUAL(base.a, 232);

		state.garbageCollect();
		TEST_CHECK(state("assert(obj.a==2)"));

		state["fn"](base, 54);
		TEST_EQUAL(base.a, 232);
	}
	{//
		Base basesrc;
		Base& base = basesrc;
		base.a = 232;
		state["obj"] = base;
		TEST_CHECK(state("assert(obj.a==232)"));
		TEST_CHECK(state("obj.a = 2"));
		TEST_CHECK(state("assert(obj.a==2)"));
		TEST_EQUAL(base.a, 232);

		state.garbageCollect();
		TEST_CHECK(state("assert(obj.a==2)"));

		state["fn"](base, 54);
		TEST_EQUAL(base.a, 232);
	}
	{//
		Base basesrc;
		const Base& base = basesrc;
		basesrc.a = 232;
		state["obj"] = base;
		TEST_CHECK(state("assert(obj.a==232)"));
		TEST_CHECK(state("obj.a = 2"));
		TEST_CHECK(state("assert(obj.a==2)"));
		TEST_EQUAL(base.a, 232);

		state.garbageCollect();
		TEST_CHECK(state("assert(obj.a==2)"));

		state["fn"](base, 54);
		TEST_EQUAL(base.a, 232);
	}
}
KAGUYA_TEST_FUNCTION_DEF(object_take_const_pointer)(kaguya::State& state)
{
	state["Base"].setClass(kaguya::ClassMetatable<Base>()
		.addConstructor()
		.addProperty("a", &Base::a)
		);
	TEST_CHECK(state("fn = function(object,value) object.a = value end"));

	Base basesrc;
	basesrc.a = 232;
	const Base& base = basesrc;
	state["obj"] = kaguya::standard::ref(base);
	TEST_CHECK(state("assert(obj.a==232)"));
	//		TEST_CHECK(!state("obj.a = 2"));//cannot assign
	TEST_CHECK(state("assert(obj.a==232)"));
	TEST_EQUAL(base.a, 232);

	basesrc.a = 22;
	TEST_CHECK(state("assert(obj.a==22)"));

	state.garbageCollect();
	TEST_CHECK(state("assert(obj.a==22)"));

	//		state["fn"](base, 54);//cannot assign
	TEST_EQUAL(base.a, 22);
}
KAGUYA_TEST_FUNCTION_DEF(copy_constructor)(kaguya::State& state)
{
	state["ABC"].setClass(kaguya::ClassMetatable<ABC>()
		.addConstructor<const char*>()
		.addConstructor<int>()
		.addConstructor<std::string>()
		.addConstructor<int, const std::string&>()
		.addConstructor<const std::string&, int>()
		.addMember("getString", &ABC::getString)
		.addMember("setString", &ABC::setString)
		.addMember("getInt", &ABC::getInt)
		.addMember("references", static_cast<ABC& (ABC::*)()>(&ABC::references))
		.addMember("references", static_cast<const ABC& (ABC::*)()const>(&ABC::references))
		.addMember("const_pointer", &ABC::const_pointer)
		.addMember("pointer", &ABC::pointer)
		.addMember("copy", &ABC::copy)
		.addMember("shared_copy", &ABC::shared_copy)
		);


	TEST_CHECK(state("value = assert(ABC.new(64,'string_value3'))"));
	TEST_CHECK(state("value2 = assert(value:copy())"));
	TEST_CHECK(state("assert(value2:getString() == 'string_value3')"));
	TEST_CHECK(state("assert(value2:getInt() == 64)"));
	TEST_CHECK(state("value3 = assert(value:references())"));
	TEST_CHECK(state("cvalue = assert(value:const_pointer())"));
	TEST_CHECK(state("assert(cvalue:getString() == 'string_value3')"));
	TEST_CHECK(state("assert(cvalue:getInt() == 64)"));

	TEST_CHECK(state("assert(value3:getString() == 'string_value3')"));
	TEST_CHECK(state("assert(value3:getInt() == 64)"));
	TEST_CHECK(state("value4 = assert(value:pointer())"));
	TEST_CHECK(state("assert(value4:getString() == 'string_value3')"));
	TEST_CHECK(state("assert(value4:getInt() == 64)"));

	TEST_CHECK(state("value5 = assert(value:shared_copy())"));
	TEST_CHECK(state("value =1"));
	state.garbageCollect();//warning!! value3 and value4 to dangling pointer
	TEST_CHECK(state("assert(value5:getString() == 'string_value3')"));
	TEST_CHECK(state("assert(value5:getInt() == 64)"));


	{
		kaguya::standard::shared_ptr<ABC> shared_ptr(new ABC("shared_object", 53));
		state["shared_object"] = shared_ptr;
	}
	TEST_CHECK(state("assert(shared_object:getInt() == 53)"));
	TEST_CHECK(state("assert(shared_object:getString() =='shared_object')"));


};
KAGUYA_TEST_FUNCTION_DEF(object_take_reference)(kaguya::State& state)
{
	state["Base"].setClass(kaguya::ClassMetatable<Base>()
		.addConstructor()
		.addProperty("a", &Base::a)
		);
	TEST_CHECK(state("fn = function(object,value) object.a = value end"));

	Base base;
	base.a = 232;
	state["obj"] = kaguya::standard::ref(base);
	TEST_CHECK(state("assert(obj.a==232)"));
	TEST_CHECK(state("obj.a = 2"));
	TEST_CHECK(state("assert(obj.a==2)"));
	TEST_EQUAL(base.a, 2);

	state.garbageCollect();
	TEST_CHECK(state("assert(obj.a==2)"));

	state["fn"](kaguya::standard::ref(base), 54);
	TEST_EQUAL(base.a, 54);
}