/*
Ousía
Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
namespace ousia {
namespace {
struct TestObject {
TestObject(int a) : a(a) {}
int a;
static Variant getA(const TestObject *obj) { return Variant{obj->a}; }
static void setA(const Variant &value, TestObject *obj)
{
if (value.isInt()) {
obj->a = value.asInt();
}
}
};
}
static Variant getString(const TestObject *obj) { return "foo"; }
TEST(Getter, construction)
{
{
Getter getter{};
ASSERT_FALSE(getter.isValid());
}
{
Getter getter{nullptr};
ASSERT_FALSE(getter.isValid());
}
{
Getter getter{TestObject::getA};
ASSERT_TRUE(getter.isValid());
}
}
TEST(Getter, validation)
{
std::shared_ptr type =
std::make_shared(&RttiTypes::Int);
TestObject obj{123};
{
// No specifiy type set, strings can be returned
Getter getter{getString};
ASSERT_EQ("foo", getter.get(&obj));
}
{
// Int type set, returning strings is an exception
Getter getter{getString};
getter.propertyType = type;
ASSERT_THROW(getter.get(&obj), LoggableException);
}
{
Getter getter{TestObject::getA};
// Basic functionality
ASSERT_EQ(123, getter.call(Variant::arrayType{}, &obj));
// Exception should be thrown if an argument is explicitly given
ASSERT_THROW(getter.call(Variant::arrayType{1}, &obj),
PropertyException);
}
}
TEST(Setter, construction)
{
{
Setter setter{};
ASSERT_FALSE(setter.isValid());
}
{
Setter setter{nullptr};
ASSERT_FALSE(setter.isValid());
}
{
Setter setter{TestObject::setA};
ASSERT_TRUE(setter.isValid());
}
}
TEST(Setter, validation)
{
std::shared_ptr type =
std::make_shared(&RttiTypes::Int);
TestObject obj{123};
Setter setter{TestObject::setA};
// An exception should be thrown if not exactly one argument is passed to
// the setter
ASSERT_THROW(setter.call(Variant::arrayType{}, &obj), PropertyException);
ASSERT_THROW(setter.call(Variant::arrayType{1, 2}, &obj),
PropertyException);
setter.call(Variant::arrayType{42}, &obj); // OK
ASSERT_EQ(42, obj.a);
// No specifiy type set, any value can be given (does not crash because of
// explicity type check in the callback function, see above).
setter.set("foo", &obj);
ASSERT_EQ(42, obj.a);
setter.propertyType = type;
ASSERT_THROW(setter.set("foo", &obj), LoggableException);
setter.set(123, &obj);
ASSERT_EQ(123, obj.a);
}
TEST(Property, construction)
{
TestObject obj{123};
{
ASSERT_THROW(Property property{nullptr}, PropertyException);
}
{
Property property{TestObject::getA};
ASSERT_TRUE(property.isReadonly());
ASSERT_THROW(property.set(42, &obj), LoggableException);
}
{
Property property{TestObject::getA, TestObject::setA};
ASSERT_FALSE(property.isReadonly());
ASSERT_EQ(123, property.get(&obj).asInt());
property.set(42, &obj);
ASSERT_EQ(42, property.get(&obj).asInt());
property.set("bla", &obj);
ASSERT_EQ(42, property.get(&obj).asInt());
}
{
Property property{&RttiTypes::Int, TestObject::getA,
TestObject::setA};
ASSERT_FALSE(property.isReadonly());
ASSERT_EQ(42, property.get(&obj).asInt());
property.set(123, &obj);
ASSERT_EQ(123, property.get(&obj).asInt());
ASSERT_THROW(property.set("bla", &obj), LoggableException);
}
}
}