Back to index

unity  6.0.0
test_home_lens.cpp
Go to the documentation of this file.
00001 #include <gtest/gtest.h>
00002 #include <glib-object.h>
00003 #include <dee.h>
00004 #include <string>
00005 #include <iostream>
00006 #include <stdexcept>
00007 #include <map>
00008 #include <memory>
00009 #include <sigc++/signal.h>
00010 #include <sigc++/trackable.h>
00011 
00012 #include <UnityCore/GLibWrapper.h>
00013 #include <UnityCore/Variant.h>
00014 #include <UnityCore/HomeLens.h>
00015 #include <UnityCore/Lens.h>
00016 #include <UnityCore/Lenses.h>
00017 
00018 #include "test_utils.h"
00019 
00020 using namespace std;
00021 using namespace unity::dash;
00022 
00023 namespace
00024 {
00025 
00026 /*
00027  * FORWARDS
00028  */
00029 
00030 class StaticTestLens;
00031 
00032 typedef struct {
00033   StaticTestLens* lens;
00034   gchar*          search_string;
00035 } LensSearchClosure;
00036 
00037 static gboolean dispatch_global_search(gpointer userdata);
00038 
00039 
00040 /*
00041  * Mock Lens instance that does not use DBus. The default search does like this:
00042  * For input "bar" output:
00043  *
00044  * i = 0
00045  * for letter in "bar":
00046  *   put result row [ "uri+$letter+$lens_id", "icon+$letter+$lens_id", i % 3, "mime+$letter+$lens_id", ...]
00047  *   i++
00048  *
00049  * The mock lens has 3 categories:
00050  *
00051  *  0) "cat0+$lens_id"
00052  *  1) "cat1+$lens_id"
00053  *  2) "Shared cat"
00054  */
00055 class StaticTestLens : public Lens
00056 {
00057 public:
00058   typedef std::shared_ptr<StaticTestLens> Ptr;
00059 
00060   StaticTestLens(string const& id, string const& name, string const& description, string const& search_hint)
00061     : Lens(id, "", "", name, "lens-icon.png",
00062            description, search_hint, true, "",
00063            ModelType::LOCAL)
00064   {
00065     search_in_global(true);
00066 
00067     DeeModel* cats = categories()->model();
00068     DeeModel* results = global_results()->model();
00069     DeeModel* flters = filters()->model();
00070 
00071     // Set model schemas
00072     dee_model_set_schema(cats, "s", "s", "s", "a{sv}", NULL);
00073     dee_model_set_schema(results, "s", "s", "u", "s", "s", "s", "s", NULL);
00074     dee_model_set_schema(flters, "s", "s", "s", "s", "a{sv}", "b", "b", "b", NULL);
00075 
00076     // Populate categories model
00077     ostringstream cat0, cat1;
00078     cat0 << "cat0+" << id;
00079     cat1 << "cat1+" << id;
00080     GVariantBuilder b;
00081     g_variant_builder_init(&b, G_VARIANT_TYPE_VARDICT);
00082     GVariant *asv = g_variant_builder_end(&b);
00083 
00084     dee_model_append(cats, cat0.str().c_str(), "icon.png", "tile-vertical", asv);
00085     dee_model_append(cats, cat1.str().c_str(), "icon.png", "tile-vertical", asv);
00086     dee_model_append(cats, "Shared cat", "icon.png", "tile-vertical", asv);
00087   }
00088 
00089   virtual ~StaticTestLens() {}
00090 
00091   virtual void DoGlobalSearch(string const& search_string)
00092   {
00093     DeeModel* model = global_results()->model();
00094     GVariant** row_buf = g_new(GVariant*, 8);
00095 
00096     row_buf[1] = g_variant_new_string("");
00097     row_buf[3] = g_variant_new_string("");
00098     row_buf[4] = g_variant_new_string("");
00099     row_buf[5] = g_variant_new_string("");
00100     row_buf[6] = g_variant_new_string("");
00101     row_buf[7] = NULL;
00102 
00103     unsigned int i;
00104     for (i = 0; i < search_string.size(); i++)
00105     {
00106       ostringstream uri;
00107       uri << "uri+" << search_string.at(i) << "+" << id();
00108       row_buf[0] = g_variant_new_string(uri.str().c_str());
00109       row_buf[2] = g_variant_new_uint32(i % 3);
00110 
00111       dee_model_append_row(model, row_buf);
00112     }
00113 
00114     g_free(row_buf);
00115   }
00116 
00117   void GlobalSearch(string const& search_string)
00118   {
00119     /* Dispatch search async, because that's */
00120     LensSearchClosure* closure = g_new0(LensSearchClosure, 1);
00121     closure->lens = this;
00122     closure->search_string = g_strdup(search_string.c_str());
00123     g_idle_add(dispatch_global_search, closure);
00124   }
00125 
00126   void Search(string const& search_string)
00127   {
00128 
00129   }
00130 
00131   void Activate(string const& uri)
00132   {
00133 
00134   }
00135 
00136   void Preview(string const& uri)
00137   {
00138 
00139   }
00140 
00141 };
00142 
00143 static gboolean dispatch_global_search(gpointer userdata)
00144 {
00145   LensSearchClosure* closure = (LensSearchClosure*) userdata;
00146 
00147   closure->lens->DoGlobalSearch(closure->search_string);
00148 
00149   g_free(closure->search_string);
00150   g_free(closure);
00151 
00152   return FALSE;
00153 }
00154 
00155 /*
00156  * Mock Lenses class
00157  */
00158 class StaticTestLenses : public Lenses
00159 {
00160 public:
00161   typedef std::shared_ptr<StaticTestLenses> Ptr;
00162 
00163   StaticTestLenses()
00164   {
00165     count.SetGetterFunction(sigc::mem_fun(&list_, &Lenses::LensList::size));
00166   }
00167 
00168   virtual ~StaticTestLenses() {}
00169 
00170   Lenses::LensList GetLenses() const
00171   {
00172     return list_;
00173   }
00174 
00175   Lens::Ptr GetLens(std::string const& lens_id) const
00176   {
00177     for (auto lens : list_)
00178     {
00179       if (lens->id() == lens_id)
00180         return lens;
00181     }
00182     return Lens::Ptr();
00183   }
00184 
00185   Lens::Ptr GetLensAtIndex(std::size_t index) const
00186   {
00187     return list_.at(index);
00188   }
00189 
00190 protected:
00191   Lenses::LensList list_;
00192 };
00193 
00194 class TwoStaticTestLenses : public StaticTestLenses
00195 {
00196 public:
00197   TwoStaticTestLenses()
00198   : lens_1_(new StaticTestLens("first.lens", "First Lens", "The very first lens", "First search hint"))
00199   , lens_2_(new StaticTestLens("second.lens", "Second Lens", "The second lens", "Second search hint"))
00200   {
00201     list_.push_back(lens_1_);
00202     list_.push_back(lens_2_);
00203   }
00204 
00205 private:
00206   Lens::Ptr lens_1_;
00207   Lens::Ptr lens_2_;
00208 };
00209 
00210 TEST(TestHomeLens, TestConstruction)
00211 {
00212   HomeLens home_lens_("name", "description", "searchhint");
00213 
00214   EXPECT_EQ(home_lens_.id(), "home.lens");
00215   EXPECT_EQ(home_lens_.connected, false);
00216   EXPECT_EQ(home_lens_.search_in_global, false);
00217   EXPECT_EQ(home_lens_.name, "name");
00218   EXPECT_EQ(home_lens_.description, "description");
00219   EXPECT_EQ(home_lens_.search_hint, "searchhint");
00220 }
00221 
00222 TEST(TestHomeLens, TestInitiallyEmpty)
00223 {
00224   HomeLens home_lens_("name", "description", "searchhint");
00225   DeeModel* results = home_lens_.results()->model();
00226   DeeModel* categories = home_lens_.categories()->model();;
00227   DeeModel* filters = home_lens_.filters()->model();;
00228 
00229   EXPECT_EQ(dee_model_get_n_rows(results), 0);
00230   EXPECT_EQ(dee_model_get_n_rows(categories), 0);
00231   EXPECT_EQ(dee_model_get_n_rows(filters), 0);
00232 
00233   EXPECT_EQ(home_lens_.count(), 0);
00234 }
00235 
00236 TEST(TestHomeLens, TestTwoStaticLenses)
00237 {
00238   HomeLens home_lens_("name", "description", "searchhint");
00239   TwoStaticTestLenses lenses_;
00240 
00241   home_lens_.AddLenses(lenses_);
00242 
00243   EXPECT_EQ(home_lens_.count, (size_t) 2);
00244 
00245   /* Test iteration of registered lensess */
00246   map<string,string> remaining;
00247   remaining["first.lens"] = "";
00248   remaining["second.lens"] = "";
00249   for (auto lens : home_lens_.GetLenses())
00250   {
00251     remaining.erase(lens->id());
00252   }
00253 
00254   EXPECT_EQ(remaining.size(), 0);
00255 
00256   /* Test sorting and GetAtIndex */
00257   EXPECT_EQ(home_lens_.GetLensAtIndex(0)->id(), "first.lens");
00258   EXPECT_EQ(home_lens_.GetLensAtIndex(1)->id(), "second.lens");
00259 }
00260 
00261 TEST(TestHomeLens, TestCategoryMerging)
00262 {
00263   HomeLens home_lens_("name", "description", "searchhint");
00264   TwoStaticTestLenses lenses_;
00265   DeeModel* cats = home_lens_.categories()->model();
00266   DeeModelIter* iter;
00267   unsigned int cat0_first = 0,
00268                 cat1_first = 1,
00269                 cat_shared = 2,
00270                 cat0_second = 3,
00271                 cat1_second = 4;
00272   const unsigned int NAME_COLUMN = 0;
00273 
00274   home_lens_.AddLenses(lenses_);
00275 
00276   EXPECT_EQ(dee_model_get_n_rows(cats), 5); // 5 because each lens has 3 cats, but 1 is shared between them
00277 
00278   /* Validate the merged categories */
00279   iter = dee_model_get_iter_at_row(cats, cat0_first);
00280   EXPECT_EQ("cat0+first.lens", string(dee_model_get_string(cats, iter, NAME_COLUMN)));
00281 
00282   iter = dee_model_get_iter_at_row(cats, cat1_first);
00283   EXPECT_EQ("cat1+first.lens", string(dee_model_get_string(cats, iter, NAME_COLUMN)));
00284 
00285   iter = dee_model_get_iter_at_row(cats, cat_shared);
00286   EXPECT_EQ("Shared cat", string(dee_model_get_string(cats, iter, NAME_COLUMN)));
00287 
00288   iter = dee_model_get_iter_at_row(cats, cat0_second);
00289   EXPECT_EQ("cat0+second.lens", string(dee_model_get_string(cats, iter, NAME_COLUMN)));
00290 
00291   iter = dee_model_get_iter_at_row(cats, cat1_second);
00292   EXPECT_EQ("cat1+second.lens", string(dee_model_get_string(cats, iter, NAME_COLUMN)));
00293 }
00294 
00295 // It's not that we must not support filters. It is just not implemented yet.
00296 // But we actively test against it to make sure we don't end up with broken
00297 // filters in the UI. When/if we land support for filters on the home screen
00298 // this test should obviously be removed
00299 TEST(TestHomeLens, TestIgnoreFilters)
00300 {
00301   HomeLens home_lens_("name", "description", "searchhint");
00302   TwoStaticTestLenses lenses_;
00303   DeeModel* filters = home_lens_.filters()->model();
00304 
00305   EXPECT_EQ(dee_model_get_n_rows(filters), 0);
00306 }
00307 
00308 TEST(TestHomeLens, TestOneSearch)
00309 {
00310   HomeLens home_lens_("name", "description", "searchhint");
00311   TwoStaticTestLenses lenses_;
00312   DeeModel* results = home_lens_.results()->model();
00313   DeeModel* cats = home_lens_.categories()->model();
00314   DeeModel* filters = home_lens_.filters()->model();
00315   DeeModelIter* iter;
00316   unsigned int cat0_first = 0,
00317                 cat1_first = 1,
00318                 cat_shared = 2,
00319                 cat0_second = 3,
00320                 cat1_second = 4;
00321   const unsigned int URI_COLUMN = 0;
00322   const unsigned int CAT_COLUMN = 2;
00323 
00324   home_lens_.AddLenses(lenses_);
00325 
00326   home_lens_.Search("ape");
00327 
00328   Utils::WaitForTimeoutMSec();
00329 
00330   /* Validate counts */
00331   EXPECT_EQ(dee_model_get_n_rows(results), 6); // 3 hits from each lens
00332   EXPECT_EQ(dee_model_get_n_rows(cats), 5); // 5 because each lens has 3 cats, but 1 is shared between them
00333   EXPECT_EQ(dee_model_get_n_rows(filters), 0); // We ignore filters deliberately currently
00334 
00335   /* Validate results. In particular that we get the correct merged
00336    * category offsets assigned */
00337   iter = dee_model_get_iter_at_row(results, 0);
00338   EXPECT_EQ(string("uri+a+first.lens"), string(dee_model_get_string(results, iter, URI_COLUMN)));
00339   EXPECT_EQ(cat0_first, dee_model_get_uint32(results, iter, CAT_COLUMN));
00340 
00341   iter = dee_model_get_iter_at_row(results, 1);
00342   EXPECT_EQ(string("uri+p+first.lens"), string(dee_model_get_string(results, iter, URI_COLUMN)));
00343   EXPECT_EQ(cat1_first, dee_model_get_uint32(results, iter, CAT_COLUMN));
00344 
00345   iter = dee_model_get_iter_at_row(results, 2);
00346   EXPECT_EQ(string("uri+e+first.lens"), string(dee_model_get_string(results, iter, URI_COLUMN)));
00347   EXPECT_EQ(cat_shared, dee_model_get_uint32(results, iter, CAT_COLUMN));
00348 
00349   iter = dee_model_get_iter_at_row(results, 3);
00350   EXPECT_EQ(string("uri+a+second.lens"), string(dee_model_get_string(results, iter, URI_COLUMN)));
00351   EXPECT_EQ(cat0_second, dee_model_get_uint32(results, iter, CAT_COLUMN));
00352 
00353   iter = dee_model_get_iter_at_row(results, 4);
00354   EXPECT_EQ(string("uri+p+second.lens"), string(dee_model_get_string(results, iter, URI_COLUMN)));
00355   EXPECT_EQ(cat1_second, dee_model_get_uint32(results, iter, CAT_COLUMN));
00356 
00357   iter = dee_model_get_iter_at_row(results, 5);
00358   EXPECT_EQ(string("uri+e+second.lens"), string(dee_model_get_string(results, iter, URI_COLUMN)));
00359   EXPECT_EQ(cat_shared, dee_model_get_uint32(results, iter, CAT_COLUMN));
00360 }
00361 
00362 }