1 /* This file is part of Step
2    Copyright (C) 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
3 
4    StepCore library is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8 
9    StepCore library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with StepCore; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18 
19 #include "test_metaobject.h"
20 #include "stepcore/object.h"
21 #include <QString>
22 #include <QMetaType>
23 #include <QTest>
24 
25 struct MetaObjectTestType
26 {
27     int value;
MetaObjectTestTypeMetaObjectTestType28     MetaObjectTestType(int v): value(v) {}
MetaObjectTestTypeMetaObjectTestType29     MetaObjectTestType(): value(0) {}
30 };
31 Q_DECLARE_METATYPE( MetaObjectTestType )
32 
33 class MetaObjectTestInterface
34 {
35     STEPCORE_OBJECT(MetaObjectTestInterface)
36 
37 public:
~MetaObjectTestInterface()38     virtual ~MetaObjectTestInterface() {}
property1() const39     double property1() const { return _property1; }
setProperty1(double property1)40     void setProperty1(double property1) { _property1 = property1; }
41 
42 protected:
43     double _property1;
44 };
45 
46 class MetaObjectTestObject: public StepCore::Object, public MetaObjectTestInterface
47 {
48     STEPCORE_OBJECT(MetaObjectTestObject)
49 
50 public:
property2() const51     int property2() const { return 2; }
52 
property3() const53     const MetaObjectTestType& property3() const { return _property3; }
setProperty3(const MetaObjectTestType & property3)54     void setProperty3(const MetaObjectTestType& property3) { _property3 = property3; }
55 
property4() const56     MetaObjectTestType property4() const { return _property4; }
setProperty4(MetaObjectTestType property4)57     bool setProperty4(MetaObjectTestType property4) {
58         if(property4.value < 0) return false;
59         _property4 = property4; return true;
60     }
61 
62 protected:
63     double             _property2;
64     MetaObjectTestType _property3;
65     MetaObjectTestType _property4;
66 };
67 
68 namespace StepCore {
typeToString(const MetaObjectTestType & v)69 template<> inline QString typeToString(const MetaObjectTestType& v)
70 {
71     return QString::number(v.value);
72 }
73 
stringToType(const QString & s,bool * ok)74 template<> inline MetaObjectTestType stringToType(const QString& s, bool* ok)
75 {
76     return MetaObjectTestType(s.toInt(ok));
77 }
78 
variantToType(const QVariant & v,bool * ok)79 template<> inline MetaObjectTestType variantToType(const QVariant& v, bool* ok)
80 {
81     if(v.userType() == qMetaTypeId<MetaObjectTestType>()) {
82         *ok = true; return v.value<MetaObjectTestType>();
83     }
84     QVariant vc(v); *ok = vc.convert(QVariant::Int);
85     return MetaObjectTestType(vc.value<int>());
86 }
87 
88 }
89 
90 STEPCORE_META_OBJECT(MetaObjectTestInterface, "MetaObjectTestInterface", "TestInterface", StepCore::MetaObject::ABSTRACT,,
91         STEPCORE_PROPERTY_RW(double, property1, "property1", "m", "Property1", property1, setProperty1))
92 
93 STEPCORE_META_OBJECT(MetaObjectTestObject, "MetaObjectTestObject", "TestObject", 0,
94         STEPCORE_SUPER_CLASS(StepCore::Object) STEPCORE_SUPER_CLASS(MetaObjectTestInterface),
95         STEPCORE_PROPERTY_R (int,   property2, "property2", STEPCORE_UNITS_1, "Property2", property2)
96         STEPCORE_PROPERTY_RW(MetaObjectTestType, property3, "property3", STEPCORE_UNITS_NULL, "Property3", property3, setProperty3)
97         STEPCORE_PROPERTY_RW(MetaObjectTestType, property4, "property4", STEPCORE_UNITS_NULL, "Property4", property4, setProperty4)
98         )
99 
testMetaObject()100 void TestMetaobject::testMetaObject()
101 {
102     /* Abstract class: can't create */
103     QVERIFY( MetaObjectTestInterface::staticMetaObject()->isAbstract() );
104     QVERIFY( MetaObjectTestInterface::staticMetaObject()->newObject() == NULL );
105 
106     /* Normal class: should create */
107     QVERIFY( !MetaObjectTestObject::staticMetaObject()->isAbstract() );
108     StepCore::Object* object = MetaObjectTestObject::staticMetaObject()->newObject();
109     QVERIFY( object != NULL);
110     MetaObjectTestObject* testObject = dynamic_cast<MetaObjectTestObject*>(object);
111     QVERIFY( testObject != NULL );
112 
113     QVERIFY( object->metaObject() == MetaObjectTestObject::staticMetaObject() );
114 
115     /* Class name */
116     const StepCore::MetaObject* metaObject = testObject->metaObject();
117     QCOMPARE( QString(metaObject->className()), QString("MetaObjectTestObject") );
118 
119     /* Super classes list */
120     QCOMPARE( metaObject->superClassCount(), 2 );
121     QCOMPARE( QString(metaObject->superClass(0)->className()), QString("Object") );
122     QCOMPARE( QString(metaObject->superClass(1)->className()), QString("MetaObjectTestInterface") );
123 
124     /* Inheritance */
125     QVERIFY( metaObject->inherits(StepCore::Object::staticMetaObject()) );
126     QVERIFY( metaObject->inherits(MetaObjectTestInterface::staticMetaObject()) );
127     QVERIFY( metaObject->inherits(metaObject) );
128     QVERIFY( !MetaObjectTestInterface::staticMetaObject()->inherits(metaObject) );
129 
130     QVERIFY( metaObject->inherits("Object") );
131     QVERIFY( metaObject->inherits("MetaObjectTestInterface") );
132     QVERIFY( metaObject->inherits("MetaObjectTestObject") );
133     QVERIFY( !metaObject->inherits("NotClass") );
134     QVERIFY( !MetaObjectTestInterface::staticMetaObject()->inherits("MetaObjectTestObject") );
135 
136     /* Property count */
137     QCOMPARE( metaObject->classPropertyCount(), 3 );
138     QCOMPARE( metaObject->propertyCount(), 5 );
139 
140     /* Property lookup */
141     QVERIFY( metaObject->property("name") == metaObject->property(0) );
142     QVERIFY( metaObject->property("property1") == metaObject->property(1) );
143     QVERIFY( metaObject->property("property2") == metaObject->property(2) );
144     QVERIFY( metaObject->property("property3") == metaObject->property(3) );
145     QVERIFY( metaObject->property("property4") == metaObject->property(4) );
146     QVERIFY( metaObject->property("notProperty") == NULL );
147 
148     const StepCore::MetaProperty* property;
149 
150     /* QString property inherited from first base class */
151     property = testObject->metaObject()->property(0);
152     QCOMPARE( QString(property->name()), QString("name") );
153     QVERIFY( property->isReadable() );
154     QVERIFY( property->isWritable() );
155     QVERIFY( property->isStored() );
156 
157     QVERIFY( property->writeString(testObject, "test1") );
158     QCOMPARE( object->name(), QString("test1") );
159     QVERIFY( property->writeVariant(testObject, QVariant(QString("test2"))) );
160     QCOMPARE( object->name(), QString("test2") );
161 
162     QCOMPARE( property->readString(object), QString("test2") );
163     QCOMPARE( property->readVariant(object), QVariant(QString("test2")) );
164 
165     /* double property inherited from second base class */
166     property = testObject->metaObject()->property(1);
167     QCOMPARE( QString(property->name()), QString("property1") );
168 
169     QVERIFY( property->writeString(object, "1.1") );
170     QCOMPARE( testObject->property1(), 1.1 );
171     QVERIFY( property->writeVariant(object, QVariant(2.2)) );
172     QCOMPARE( testObject->property1(), 2.2 );
173     QCOMPARE( property->readString(object), QString("2.2") );
174     QCOMPARE( property->readVariant(object), QVariant(2.2) );
175 
176     QVERIFY( !property->writeString(object, "not number") );
177     QCOMPARE( testObject->property1(), 2.2 );
178     QVERIFY( !property->writeVariant(object, QVariant("not number")) );
179     QCOMPARE( testObject->property1(), 2.2 );
180 
181     /* double read-only property */
182     property = testObject->metaObject()->property(2);
183     QCOMPARE( QString(property->name()), QString("property2") );
184     QVERIFY( property->isReadable() );
185     QVERIFY( !property->isWritable() );
186     QVERIFY( !property->isStored() );
187 
188     QVERIFY( !property->writeString(object, "10") );
189     QCOMPARE( testObject->property2(), 2 );
190     QCOMPARE( property->readString(object), QString("2") );
191 
192     /* MetaObjectTestType property */
193     property = testObject->metaObject()->property(3);
194     QCOMPARE( QString(property->name()), QString("property3") );
195 
196     QVERIFY( property->writeString(object, "2") );
197     QCOMPARE( testObject->property3().value, 2 );
198     QVERIFY( property->writeVariant(object, 3) );
199     QCOMPARE( testObject->property3().value, 3 );
200 
201     QCOMPARE( property->readString(object), QString("3") );
202     QCOMPARE( property->readVariant(object).value<MetaObjectTestType>().value, 3 );
203 
204     /* CloneObject */
205     StepCore::Object* clone = object->metaObject()->cloneObject(*object);
206     QCOMPARE( clone->name(), object->name() );
207     QCOMPARE( dynamic_cast<MetaObjectTestObject*>(clone)->property1(),
208               dynamic_cast<MetaObjectTestObject*>(object)->property1());
209     QCOMPARE( dynamic_cast<MetaObjectTestObject*>(clone)->property2(),
210               dynamic_cast<MetaObjectTestObject*>(object)->property2());
211     QCOMPARE( dynamic_cast<MetaObjectTestObject*>(clone)->property3().value,
212               dynamic_cast<MetaObjectTestObject*>(object)->property3().value);
213     QCOMPARE( dynamic_cast<MetaObjectTestObject*>(clone)->property4().value,
214               dynamic_cast<MetaObjectTestObject*>(object)->property4().value);
215 
216     delete object;
217     delete clone;
218 }
219 
220 QTEST_MAIN(TestMetaobject)
221