File indexing completed on 2024-05-19 15:26:48
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #include <QtTest/QtTest> 0008 #include <QPoint> 0009 #include <QMetaProperty> 0010 0011 #include "model/property/object_list_property.hpp" 0012 #include "model/property/reference_property.hpp" 0013 #include "model/document.hpp" 0014 0015 #define fake_i18n kli18n 0016 0017 using namespace glaxnimate::model; 0018 using namespace glaxnimate; 0019 0020 struct PropertyChangedInspector 0021 { 0022 PropertyChangedInspector() = default; 0023 PropertyChangedInspector(const PropertyChangedInspector&) = delete; 0024 PropertyChangedInspector& operator=(const PropertyChangedInspector&) = delete; 0025 0026 void connect(Object& obj) 0027 { 0028 QObject::connect(&obj, &Object::property_changed, [this](const BaseProperty* prop, const QVariant& value){(*this)(prop->name(), value);}); 0029 } 0030 0031 void operator()(const QString& name, const QVariant& value) 0032 { 0033 this->name = name; 0034 this->value = value; 0035 called = true; 0036 } 0037 0038 bool not_called() 0039 { 0040 return !called; 0041 } 0042 0043 bool called_with(const QString& name, const QVariant& value) 0044 { 0045 return called && this->name == name && this->value == value; 0046 } 0047 0048 void reset() 0049 { 0050 name = QString{}; 0051 value = {}; 0052 called = false; 0053 } 0054 0055 0056 QString name; 0057 QVariant value; 0058 bool called = false; 0059 }; 0060 0061 class MetaTestSubject : public DocumentNode 0062 { 0063 Q_OBJECT 0064 0065 GLAXNIMATE_PROPERTY(int, prop_scalar, 123) 0066 GLAXNIMATE_PROPERTY_REFERENCE(MetaTestSubject, prop_ref, &MetaTestSubject::valid_references, &MetaTestSubject::is_valid_reference) 0067 GLAXNIMATE_PROPERTY_LIST(MetaTestSubject, prop_list) 0068 0069 public: 0070 QIcon instance_icon() const override { return {}; } 0071 QIcon tree_icon() const override { return {}; } 0072 DocumentNode* docnode_parent() const override { return {}; } 0073 int docnode_child_count() const override { return {}; } 0074 DocumentNode* docnode_child(int) const override { return {}; } 0075 int docnode_child_index(DocumentNode*) const override { return -1; } 0076 0077 std::vector<DocumentNode*> valid_references() const 0078 { 0079 return { 0080 const_cast<MetaTestSubject*>(this) 0081 }; 0082 } 0083 bool is_valid_reference(DocumentNode* p) 0084 { 0085 return p == this; 0086 } 0087 0088 using DocumentNode::DocumentNode; 0089 0090 double foo_val(int bar) { return bar / 2.0; } 0091 double foo_val_const(int bar) const { return bar / 2.0; } 0092 double foo_ref(const int& bar) { return bar / 2.0; } 0093 double foo_ref_const(const int& bar) const { return bar / 2.0; } 0094 }; 0095 0096 0097 class TestProperty: public QObject 0098 { 0099 Q_OBJECT 0100 0101 private Q_SLOTS: 0102 0103 void test_property_default() 0104 { 0105 PropertyChangedInspector pci; 0106 Object obj(nullptr); 0107 pci.connect(obj); 0108 0109 Property<int> prop(&obj, fake_i18n("foo"), 456); 0110 QVERIFY(pci.not_called()); 0111 QCOMPARE(prop.get(), 456); 0112 } 0113 0114 void test_property_get_set() 0115 { 0116 PropertyChangedInspector pci; 0117 Object obj(nullptr); 0118 pci.connect(obj); 0119 0120 Property<int> prop(&obj, fake_i18n("foo")); 0121 prop.set(123); 0122 QVERIFY(pci.called_with("foo", 123)); 0123 QCOMPARE(prop.get(), 123); 0124 } 0125 0126 void test_property_variant() 0127 { 0128 PropertyChangedInspector pci; 0129 Object obj(nullptr); 0130 pci.connect(obj); 0131 0132 Property<int> prop(&obj, fake_i18n("foo"), 123); 0133 QCOMPARE(prop.value(), QVariant(123)); 0134 QVERIFY(prop.set_value(QVariant(456))); 0135 QVERIFY(pci.called_with("foo", 456)); 0136 QCOMPARE(prop.value(), QVariant(456)); 0137 pci.reset(); 0138 QVERIFY(!prop.set_value(QVariant(QPoint(1, 2)))); 0139 QCOMPARE(prop.get(), 456); 0140 QVERIFY(pci.not_called()); 0141 } 0142 0143 void test_traits_get_type() 0144 { 0145 QCOMPARE(model::PropertyTraits::get_type<int>(), model::PropertyTraits::Int); 0146 QCOMPARE(model::PropertyTraits::get_type<float>(), model::PropertyTraits::Float); 0147 QCOMPARE(model::PropertyTraits::get_type<bool>(), model::PropertyTraits::Bool); 0148 QCOMPARE(model::PropertyTraits::get_type<QString>(), model::PropertyTraits::String); 0149 QCOMPARE(model::PropertyTraits::get_type<model::PropertyTraits::Type>(), model::PropertyTraits::Enum); 0150 } 0151 0152 void test_metaobject() 0153 { 0154 Document doc("foo"); 0155 MetaTestSubject test_subject(&doc); 0156 MetaTestSubject other(&doc); 0157 0158 QMetaObject mop = DocumentNode::staticMetaObject; 0159 QMetaObject mo = MetaTestSubject::staticMetaObject; 0160 0161 QCOMPARE(mo.propertyCount(), mop.propertyCount() + 3); 0162 0163 QMetaProperty prop_0 = mo.property(mop.propertyCount() + 0); 0164 QCOMPARE(prop_0.name(), "prop_scalar"); 0165 QVERIFY(prop_0.isWritable()); 0166 QVERIFY(prop_0.isReadable()); 0167 QVERIFY(prop_0.isScriptable()); 0168 QCOMPARE(prop_0.read(&test_subject).toInt(), 123); 0169 QVERIFY(prop_0.write(&test_subject, QVariant(621))); 0170 QCOMPARE(prop_0.read(&test_subject).toInt(), 621); 0171 QCOMPARE(test_subject.prop_scalar.get(), 621); 0172 QVERIFY(!prop_0.write(&test_subject, QVariant("xyz"))); 0173 QCOMPARE(test_subject.prop_scalar.get(), 621); 0174 0175 QMetaProperty prop_1 = mo.property(mop.propertyCount() + 1); 0176 QCOMPARE(prop_1.name(), "prop_ref"); 0177 QVERIFY(prop_1.isWritable()); 0178 QVERIFY(prop_1.isReadable()); 0179 QVERIFY(prop_1.isScriptable()); 0180 QCOMPARE((quintptr)prop_1.read(&test_subject).value<MetaTestSubject*>(), 0); 0181 QVERIFY(prop_1.write(&test_subject, QVariant::fromValue(&test_subject))); 0182 QCOMPARE((quintptr)prop_1.read(&test_subject).value<MetaTestSubject*>(), (quintptr)&test_subject); 0183 QCOMPARE((quintptr)test_subject.prop_ref.get(), (quintptr)&test_subject); 0184 // invalid references shouldn't be set 0185 prop_1.write(&test_subject, QVariant::fromValue(&other)); 0186 QCOMPARE((quintptr)test_subject.prop_ref.get(), (quintptr)&test_subject); 0187 0188 QMetaProperty prop_2 = mo.property(mop.propertyCount() + 2); 0189 QCOMPARE(prop_2.name(), "prop_list"); 0190 QVERIFY(!prop_2.isWritable()); 0191 QVERIFY(prop_2.isReadable()); 0192 QVERIFY(prop_2.isScriptable()); 0193 QCOMPARE(prop_2.read(&test_subject).toList().size(), 0); 0194 test_subject.prop_list.insert(std::make_unique<MetaTestSubject>(&doc)); 0195 QCOMPARE(test_subject.prop_list.size(), 1); 0196 QCOMPARE(prop_2.read(&test_subject).toList().size(), 1); 0197 QCOMPARE(prop_2.read(&test_subject).toList()[0].value<MetaTestSubject*>(), test_subject.prop_list[0]); 0198 } 0199 0200 void test_callback_val() 0201 { 0202 Document doc("foo"); 0203 MetaTestSubject test_subject(&doc); 0204 PropertyCallback<double, int> pc; 0205 QVERIFY(!pc); 0206 pc = &MetaTestSubject::foo_val; 0207 QVERIFY(pc); 0208 QCOMPARE(pc(&test_subject, 3), 1.5); 0209 pc = nullptr; 0210 QVERIFY(!pc); 0211 } 0212 0213 void test_callback_val_const() 0214 { 0215 Document doc("foo"); 0216 MetaTestSubject test_subject(&doc); 0217 PropertyCallback<double, int> pc; 0218 QVERIFY(!pc); 0219 pc = &MetaTestSubject::foo_val_const; 0220 QVERIFY(pc); 0221 QCOMPARE(pc(&test_subject, 3), 1.5); 0222 pc = nullptr; 0223 QVERIFY(!pc); 0224 } 0225 0226 void test_callback_ref() 0227 { 0228 Document doc("foo"); 0229 MetaTestSubject test_subject(&doc); 0230 PropertyCallback<double, int> pc; 0231 QVERIFY(!pc); 0232 pc = &MetaTestSubject::foo_ref; 0233 QVERIFY(pc); 0234 QCOMPARE(pc(&test_subject, 3), 1.5); 0235 pc = nullptr; 0236 QVERIFY(!pc); 0237 } 0238 0239 void test_callback_ref_const() 0240 { 0241 Document doc("foo"); 0242 MetaTestSubject test_subject(&doc); 0243 PropertyCallback<double, int> pc; 0244 QVERIFY(!pc); 0245 pc = &MetaTestSubject::foo_ref_const; 0246 QVERIFY(pc); 0247 QCOMPARE(pc(&test_subject, 3), 1.5); 0248 pc = nullptr; 0249 QVERIFY(!pc); 0250 } 0251 }; 0252 0253 QTEST_GUILESS_MAIN(TestProperty) 0254 #include "test_property.moc"