on b778dca help sign in
unity8/tests/plugins/Unity/filtersbindingstest.cpp
515 lines 20 kB history raw
1/*
2* Copyright (C) 2013 Canonical, Ltd.
3*
4* Authors:
5* Pawel Stolowski <pawel.stolowski@canonical.com>
6*
7* This program is free software; you can redistribute it and/or modify
8* it under the terms of the GNU General Public License as published by
9* the Free Software Foundation; version 3.
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14* GNU General Public License for more details.
16* You should have received a copy of the GNU General Public License
17* along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
20#include "filtersbindingstest.h"
22// libunity-core
23#include <UnityCore/Filter.h>
24#include <UnityCore/MultiRangeFilter.h>
26// Qt
27#include <QTest>
28#include <QSignalSpy>
30// libunity
31#include <unity.h>
33// local
34#include "filter.h"
35#include "multirangefilter.h"
36#include "checkoptionfilter.h"
37#include "radiooptionfilter.h"
38#include "ratingsfilter.h"
39#include "ratingfilteroption.h"
40#include "genericoptionsmodel.h"
42void FiltersBindingsTest::initTestCase()
46GVariant* FiltersBindingsTest::createOptions(int numOfOptions)
48 auto vtype = g_variant_type_new("a(sssb)");
49 auto vb = g_variant_builder_new(vtype);
50 for (int i = 0; i<numOfOptions; i++) {
51 const std::string optId = "opt" + std::to_string(i);
52 const std::string optName = "Option " + std::to_string(i);
53 g_variant_builder_add(vb, "(sssb)", optId.c_str(), optName.c_str(), "", false);
54 }
55 return g_variant_builder_end(vb);
58DeeModel* FiltersBindingsTest::createFilterModel()
60 const char* filter_schema[8] = {"s", "s", "s", "s", "a{sv}", "b", "b", "b"};
61 auto model = dee_sequence_model_new();
62 dee_model_set_schema_full (DEE_MODEL(model), filter_schema, 8);
63 return model;
66void FiltersBindingsTest::createMultiRangeFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
68 createFilter(model, "filter-multirange", id, name, optionCount, true);
71void FiltersBindingsTest::createRadioOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
73 createFilter(model, "filter-radiooption", id, name, optionCount, true);
76void FiltersBindingsTest::createCheckOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
78 createFilter(model, "filter-checkoption", id, name, optionCount, true);
81void FiltersBindingsTest::createRatingsFilter(DeeModel *model, const std::string &id, const std::string &name)
83 GVariant* row[8];
85 row[0] = g_variant_new_string(id.c_str());
86 row[1] = g_variant_new_string(name.c_str());
87 row[2] = g_variant_new_string(""); // icon hint
88 row[3] = g_variant_new_string("filter-ratings");
90 GVariant *children[2];
91 GVariant *key1 = g_variant_new_string("show-all-button");
92 GVariant *key2 = g_variant_new_string("rating");
93 children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(true)));
94 children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(g_variant_new_double(0.0f)));
95 auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
97 row[4] = fhints;
98 row[5] = g_variant_new_boolean(true); // visible
99 row[6] = g_variant_new_boolean(false); // collapsed
100 row[7] = g_variant_new_boolean(false); // filtering
102 dee_model_append_row(model, row);
105void FiltersBindingsTest::createFilter(DeeModel *model, const std::string &renderer, const std::string &id, const std::string &name, int optionCount, bool showAll)
107 GVariant* row[8];
109 row[0] = g_variant_new_string(id.c_str());
110 row[1] = g_variant_new_string(name.c_str());
111 row[2] = g_variant_new_string(""); // icon hint
112 row[3] = g_variant_new_string(renderer.c_str()); // renderer
114 GVariant *children[2];
115 GVariant *key1 = g_variant_new_string("show-all-button");
116 GVariant *key2 = g_variant_new_string("options");
117 children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(showAll)));
118 children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(createOptions(optionCount)));
119 auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
121 row[4] = fhints;
122 row[5] = g_variant_new_boolean(true); // visible
123 row[6] = g_variant_new_boolean(false); // collapsed
124 row[7] = g_variant_new_boolean(false); // filtering
126 dee_model_append_row(model, row);
129void FiltersBindingsTest::testMultiRangeFilter()
131 auto model = createFilterModel();
133 createMultiRangeFilter(model, "f1", "Filter1", 1);
134 createMultiRangeFilter(model, "f2", "Filter2", 2);
135 createMultiRangeFilter(model, "f3", "Filter3", 3);
137 // create filter out of 1st row
138 auto iter = dee_model_get_first_iter(DEE_MODEL(model));
139 {
140 auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
141 QVERIFY(core_filter != nullptr);
142 auto bind_filter = Filter::newFromUnityFilter(core_filter);
143 auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
144 QVERIFY(multi_filter != nullptr);
145 auto options = multi_filter->options();
146 QCOMPARE(options->rowCount(), 2);
148 auto idx = options->index(1);
149 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
150 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
151 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
152 QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
154 QCOMPARE(id_var.toString(), QString("opt0"));
155 QCOMPARE(name_var.toString(), QString("Option 0"));
156 QCOMPARE(icon_var.toString(), QString(""));
157 QCOMPARE(active_var.toBool(), false);
159 delete multi_filter;
160 }
162 // create filter out of 2nd row
163 iter = dee_model_next(DEE_MODEL(model), iter);
164 {
165 auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
166 QVERIFY(core_filter != nullptr);
167 auto bind_filter = Filter::newFromUnityFilter(core_filter);
168 auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
169 QVERIFY(multi_filter != nullptr);
170 auto options = multi_filter->options();
171 QCOMPARE(options->rowCount(), 3);
173 auto idx = options->index(1);
174 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
175 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
176 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
177 QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
179 QCOMPARE(id_var.toString(), QString("opt0"));
180 QCOMPARE(name_var.toString(), QString("Option 0"));
181 QCOMPARE(icon_var.toString(), QString(""));
182 QCOMPARE(active_var.toBool(), false);
184 AbstractFilterOption* opt1 = options->getRawOption(1);
185 QCOMPARE(opt1->id(), QString("opt0"));
187 AbstractFilterOption* opt2 = options->getRawOption(2);
188 QCOMPARE(opt2->id(), QString("opt1"));
190 delete multi_filter;
191 }
193 // create filter out of 3nd row
194 iter = dee_model_next(DEE_MODEL(model), iter);
195 {
196 auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
197 QVERIFY(core_filter != nullptr);
198 auto bind_filter = Filter::newFromUnityFilter(core_filter);
199 auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
200 QVERIFY(multi_filter != nullptr);
201 auto options = multi_filter->options();
202 QCOMPARE(options->rowCount(), 4);
204 AbstractFilterOption* showAll = options->getRawOption(0);
205 QVERIFY(showAll->id().startsWith("show_all::"));
207 AbstractFilterOption* opt0 = options->getRawOption(1);
208 QCOMPARE(opt0->id(), QString("opt0"));
210 AbstractFilterOption* opt1 = options->getRawOption(2);
211 QCOMPARE(opt1->id(), QString("opt1"));
213 AbstractFilterOption* opt2 = options->getRawOption(3);
214 QCOMPARE(opt2->id(), QString("opt2"));
216 // verify filter options are bound to correct underlying unity options
217 auto core_multi_filter = std::dynamic_pointer_cast<unity::dash::MultiRangeFilter>(core_filter);
218 QCOMPARE(QString::fromStdString(core_multi_filter->options()[0]->id()), QString("opt0"));
219 QCOMPARE(QString::fromStdString(core_multi_filter->options()[1]->id()), QString("opt1"));
220 QCOMPARE(QString::fromStdString(core_multi_filter->options()[2]->id()), QString("opt2"));
222 QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
223 QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
224 QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
226 // test active property changes
227 QCOMPARE(opt0->active(), false);
229 opt0->setActive(true); // activate 1st option
230 QCOMPARE(opt0spy.count(), 1);
231 QCOMPARE(opt1spy.count(), 0);
232 QCOMPARE(opt2spy.count(), 0);
233 QCOMPARE(opt0->active(), true);
234 QCOMPARE(opt1->active(), false);
235 QCOMPARE(opt2->active(), false);
237 opt1->setActive(true);
238 QCOMPARE(opt0spy.count(), 2);
239 QCOMPARE(opt1spy.count(), 1);
240 QCOMPARE(opt2spy.count(), 0);
241 QCOMPARE(opt0->active(), false); //1st combined option gets deactivated
242 QCOMPARE(opt1->active(), true);
243 QCOMPARE(opt2->active(), false);
245 opt1->setActive(false); // and de-activate it
246 QCOMPARE(opt0spy.count(), 2);
247 QCOMPARE(opt1spy.count(), 2);
248 QCOMPARE(opt2spy.count(), 0);
249 QCOMPARE(opt0->active(), false);
250 QCOMPARE(opt1->active(), false);
251 QCOMPARE(opt2->active(), false);
253 opt2->setActive(true); // activate another combined option
254 QCOMPARE(opt0spy.count(), 2);
255 QCOMPARE(opt1spy.count(), 2);
256 QCOMPARE(opt2spy.count(), 1);
257 QCOMPARE(opt0->active(), false);
258 QCOMPARE(opt1->active(), false);
259 QCOMPARE(opt2->active(), true);
261 delete multi_filter;
262 }
265void FiltersBindingsTest::testCheckOptionFilter()
267 auto model = createFilterModel();
269 createCheckOptionFilter(model, "f1", "Filter1", 3);
271 // create filter out of 1st row
272 auto iter = dee_model_get_first_iter(DEE_MODEL(model));
273 {
274 auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
275 QVERIFY(core_filter != nullptr);
276 auto bind_filter = Filter::newFromUnityFilter(core_filter);
277 auto check_filter = dynamic_cast<CheckOptionFilter*>(bind_filter);
278 QVERIFY(check_filter != nullptr);
279 auto options = check_filter->options();
280 QCOMPARE(options->rowCount(), 4);
282 QCOMPARE(check_filter->id(), QString("f1"));
283 QCOMPARE(check_filter->name(), QString("Filter1"));
284 QCOMPARE(check_filter->iconHint(), QString(""));
285 QCOMPARE(check_filter->rendererName(), QString("filter-checkoption"));
286 QCOMPARE(check_filter->visible(), true);
287 QCOMPARE(check_filter->collapsed(), false);
288 QCOMPARE(check_filter->filtering(), false);
290 auto idx = options->index(1);
291 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
292 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
293 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
294 QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
296 QCOMPARE(id_var.toString(), QString("opt0"));
297 QCOMPARE(name_var.toString(), QString("Option 0"));
298 QCOMPARE(icon_var.toString(), QString(""));
299 QCOMPARE(active_var.toBool(), false);
301 idx = options->index(2);
302 id_var = options->data(idx, GenericOptionsModel::RoleId);
303 name_var = options->data(idx, GenericOptionsModel::RoleName);
304 icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
305 active_var = options->data(idx, GenericOptionsModel::RoleActive);
307 QCOMPARE(id_var.toString(), QString("opt1"));
308 QCOMPARE(name_var.toString(), QString("Option 1"));
309 QCOMPARE(icon_var.toString(), QString(""));
310 QCOMPARE(active_var.toBool(), false);
312 AbstractFilterOption* showAll = options->getRawOption(0);
313 AbstractFilterOption* opt0 = options->getRawOption(1);
314 AbstractFilterOption* opt1 = options->getRawOption(2);
315 AbstractFilterOption* opt2 = options->getRawOption(3);
317 QSignalSpy showAllSpy(showAll, SIGNAL(activeChanged(bool)));
318 QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
319 QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
320 QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
321 QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
323 // test active property changes
324 QCOMPARE(showAll->active(), false);
325 QCOMPARE(opt0->active(), false);
326 QCOMPARE(opt1->active(), false);
327 QCOMPARE(opt2->active(), false);
329 opt0->setActive(true);
330 QCOMPARE(showAllSpy.count(), 0);
331 QCOMPARE(opt0spy.count(), 1);
332 QCOMPARE(opt1spy.count(), 0);
333 QCOMPARE(opt2spy.count(), 0);
334 QCOMPARE(showAll->active(), false);
335 QCOMPARE(opt0->active(), true);
336 QCOMPARE(opt1->active(), false);
337 QCOMPARE(opt2->active(), false);
339 opt1->setActive(true);
340 QCOMPARE(showAllSpy.count(), 0);
341 QCOMPARE(opt0spy.count(), 2);
342 QCOMPARE(opt1spy.count(), 1);
343 QCOMPARE(opt2spy.count(), 0);
344 QCOMPARE(showAll->active(), false);
345 QCOMPARE(opt0->active(), false);
346 QCOMPARE(opt1->active(), true);
347 QCOMPARE(opt2->active(), false);
349 QCOMPARE(dataChangedSpy.count(), 3);
351 showAll->setActive(true);
352 QCOMPARE(showAllSpy.count(), 1);
353 QCOMPARE(opt0spy.count(), 2);
354 QCOMPARE(opt1spy.count(), 2);
355 QCOMPARE(opt2spy.count(), 0);
356 QCOMPARE(showAll->active(), true);
357 QCOMPARE(opt0->active(), false);
358 QCOMPARE(opt1->active(), false);
359 QCOMPARE(opt2->active(), false);
361 delete check_filter;
362 }
365void FiltersBindingsTest::testRadioOptionFilter()
367 auto model = createFilterModel();
369 createRadioOptionFilter(model, "f1", "Filter1", 3);
371 // create filter out of 1st row
372 auto iter = dee_model_get_first_iter(DEE_MODEL(model));
373 {
374 auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
375 QVERIFY(core_filter != nullptr);
376 auto bind_filter = Filter::newFromUnityFilter(core_filter);
377 auto radio_filter = dynamic_cast<RadioOptionFilter*>(bind_filter);
378 QVERIFY(radio_filter != nullptr);
379 auto options = radio_filter->options();
380 QCOMPARE(options->rowCount(), 4);
382 auto idx = options->index(0);
383 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
384 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
385 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
386 QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
388 QVERIFY(id_var.toString().startsWith("show_all::"));
389 QVERIFY(name_var.toString().size() > 0);
390 QCOMPARE(icon_var.toString(), QString(""));
391 QCOMPARE(active_var.toBool(), false);
393 idx = options->index(1);
394 id_var = options->data(idx, GenericOptionsModel::RoleId);
395 name_var = options->data(idx, GenericOptionsModel::RoleName);
396 icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
397 active_var = options->data(idx, GenericOptionsModel::RoleActive);
399 QCOMPARE(id_var.toString(), QString("opt0"));
400 QCOMPARE(name_var.toString(), QString("Option 0"));
401 QCOMPARE(icon_var.toString(), QString(""));
402 QCOMPARE(active_var.toBool(), false);
404 idx = options->index(2);
405 id_var = options->data(idx, GenericOptionsModel::RoleId);
406 name_var = options->data(idx, GenericOptionsModel::RoleName);
407 icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
408 active_var = options->data(idx, GenericOptionsModel::RoleActive);
410 QCOMPARE(id_var.toString(), QString("opt1"));
411 QCOMPARE(name_var.toString(), QString("Option 1"));
412 QCOMPARE(icon_var.toString(), QString(""));
413 QCOMPARE(active_var.toBool(), false);
415 AbstractFilterOption* opt0 = options->getRawOption(1);
416 AbstractFilterOption* opt1 = options->getRawOption(2);
417 AbstractFilterOption* opt2 = options->getRawOption(3);
419 QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
420 QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
421 QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
422 QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
424 // test active property changes
425 QCOMPARE(opt0->active(), false);
426 QCOMPARE(opt1->active(), false);
427 QCOMPARE(opt2->active(), false);
429 opt0->setActive(true);
430 QCOMPARE(opt0spy.count(), 1);
431 QCOMPARE(opt1spy.count(), 0);
432 QCOMPARE(opt2spy.count(), 0);
433 QCOMPARE(opt0->active(), true);
434 QCOMPARE(opt1->active(), false);
435 QCOMPARE(opt2->active(), false);
437 opt1->setActive(true);
438 QCOMPARE(opt0spy.count(), 2);
439 QCOMPARE(opt1spy.count(), 1);
440 QCOMPARE(opt2spy.count(), 0);
441 QCOMPARE(opt0->active(), false);
442 QCOMPARE(opt1->active(), true);
443 QCOMPARE(opt2->active(), false);
445 QCOMPARE(dataChangedSpy.count(), 3);
447 delete radio_filter;
448 }
451void FiltersBindingsTest::testRatingsFilter()
453 auto model = createFilterModel();
455 createRatingsFilter(model, "f1", "Filter1");
457 // create filter out of 1st row
458 auto iter = dee_model_get_first_iter(DEE_MODEL(model));
459 {
460 auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
461 QVERIFY(core_filter != nullptr);
462 auto bind_filter = Filter::newFromUnityFilter(core_filter);
463 auto rating_filter = dynamic_cast<RatingsFilter*>(bind_filter);
464 QVERIFY(rating_filter != nullptr);
465 auto options = rating_filter->options();
466 QCOMPARE(options->rowCount(), 6);
468 RatingFilterOption* opt[5];
469 for (int i = 0; i<5; i++) {
470 opt[i] = dynamic_cast<RatingFilterOption *>(options->getRawOption(i+1));
471 }
473 QSignalSpy opt0spy(opt[0], SIGNAL(activeChanged(bool)));
474 QSignalSpy opt4spy(opt[4], SIGNAL(activeChanged(bool)));
475 QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
477 QVERIFY(qAbs(opt[0]->value() - 0.2f) <= 0.0001f);
478 QVERIFY(qAbs(opt[1]->value() - 0.4f) <= 0.0001f);
479 QVERIFY(qAbs(opt[2]->value() - 0.6f) <= 0.0001f);
480 QVERIFY(qAbs(opt[3]->value() - 0.8f) <= 0.0001f);
481 QVERIFY(qAbs(opt[4]->value() - 1.0f) <= 0.0001f);
483 QVERIFY(rating_filter->rating() <= 0.0001f); // rating equals zero
485 // all options initially inactive
486 for (int i=0; i<5; i++) {
487 QCOMPARE(opt[i]->active(), false);
488 }
490 // verify activation for all options
491 for (int i=0; i<5; i++) {
492 opt[i]->setActive(true);
493 QCOMPARE(opt[i]->active(), true);
494 QVERIFY(rating_filter->rating() - ((i+1)*0.2f) <= 0.0001f);
496 // verify that all other options are inactive
497 for (int j=0; j<5; j++) {
498 if (i != j) {
499 QCOMPARE(opt[j]->active(), false);
500 }
501 }
502 }
504 QCOMPARE(opt0spy.count(), 2);
505 QCOMPARE(opt4spy.count(), 1);
507 opt[4]->setActive(false);
508 QVERIFY(rating_filter->rating() <= 0.0001f); // rating equals zero
509 QCOMPARE(opt4spy.count(), 2);
511 QCOMPARE(dataChangedSpy.count(), 10);
512 }
515QTEST_MAIN(FiltersBindingsTest)