Back to index

unity  6.0.0
test_introspection.cpp
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright (C) 2010 Canonical Ltd
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 3 as
00007  * published by the Free Software Foundation.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  *
00017  * Authored by: Thomi Richards <thomi.richards@canonical.com>
00018  */
00019 #include <gtest/gtest.h>
00020 #include <glib.h>
00021 #include <memory>
00022 #include <boost/foreach.hpp>
00023 
00024 #include "Introspectable.h"
00025 #include "DebugDBusInterface.h"
00026 
00027 
00028 using namespace unity::debug;
00029 
00030 class MockIntrospectable : public Introspectable
00031 {
00032 public:
00033   MockIntrospectable(std::string const& name)
00034   : name_(name)
00035   {}
00036 
00037   std::string GetName() const
00038   {
00039        return name_;
00040   }
00041   void AddProperties(GVariantBuilder* builder)
00042   {
00043     g_variant_builder_add (builder, "{sv}", "Name", g_variant_new_string (name_.c_str()) );
00044     g_variant_builder_add (builder, "{sv}", "SomeProperty", g_variant_new_string ("SomeValue") );
00045     g_variant_builder_add (builder, "{sv}", "BoolPropertyTrue", g_variant_new_boolean (TRUE) );
00046     g_variant_builder_add (builder, "{sv}", "BoolPropertyFalse", g_variant_new_boolean (FALSE) );
00047     // 8-bit integer types:
00048     g_variant_builder_add (builder, "{sv}", "BytePropertyPos", g_variant_new_byte (12) );
00049     // 16-bit integer types:
00050     g_variant_builder_add (builder, "{sv}", "Int16PropertyPos", g_variant_new_int16 (1012) );
00051     g_variant_builder_add (builder, "{sv}", "Int16PropertyNeg", g_variant_new_int16 (-1034) );
00052     g_variant_builder_add (builder, "{sv}", "UInt16PropertyPos", g_variant_new_uint16 (1056) );
00053     // 32-bit integer types:
00054     g_variant_builder_add (builder, "{sv}", "Int32PropertyPos", g_variant_new_int32 (100012) );
00055     g_variant_builder_add (builder, "{sv}", "Int32PropertyNeg", g_variant_new_int32 (-100034) );
00056     g_variant_builder_add (builder, "{sv}", "UInt32PropertyPos", g_variant_new_uint32 (100056) );
00057     // 64-bit integer types
00058     g_variant_builder_add (builder, "{sv}", "Int64PropertyPos", g_variant_new_int32 (100000012) );
00059     g_variant_builder_add (builder, "{sv}", "Int64PropertyNeg", g_variant_new_int32 (-100000034) );
00060     g_variant_builder_add (builder, "{sv}", "UInt64PropertyPos", g_variant_new_uint32 (100000056) );
00061 
00062   }
00063 private:
00064   std::string name_;
00065 };
00066 
00067 class TestIntrospection : public ::testing::Test
00068 {
00069 public:
00070   TestIntrospection()
00071   : root_(new MockIntrospectable("Unity")),
00072   dc_(new MockIntrospectable("DashController")),
00073   pc_(new MockIntrospectable("PanelController")),
00074   foo1_(new MockIntrospectable("Foo")),
00075   foo2_(new MockIntrospectable("Foo")),
00076   foo3_(new MockIntrospectable("Foo"))
00077   {
00078     root_->AddChild(dc_.get());
00079     root_->AddChild(pc_.get());
00080     dc_->AddChild(foo1_.get());
00081     dc_->AddChild(foo2_.get());
00082     dc_->AddChild(foo3_.get());
00083 
00084     //root_->SetProperty(g_variant_new("{sv}", "SomeProperty", g_variant_new_string("SomeValue")));
00085   }
00086 
00087 protected:
00088   std::shared_ptr<MockIntrospectable> root_;
00089   std::shared_ptr<MockIntrospectable> dc_;
00090   std::shared_ptr<MockIntrospectable> pc_;
00091   std::shared_ptr<MockIntrospectable> foo1_;
00092   std::shared_ptr<MockIntrospectable> foo2_;
00093   std::shared_ptr<MockIntrospectable> foo3_;
00094 
00095 };
00096 
00097 TEST_F(TestIntrospection, TestTest)
00098 {
00099   ASSERT_STREQ("Unity", root_->GetName().c_str());
00100 }
00101 
00102 TEST_F(TestIntrospection, TestVariousRootQueries)
00103 {
00104   std::list<Introspectable*> results;
00105   std::string query;
00106 
00107   results = GetIntrospectableNodesFromQuery(query, root_.get());
00108   ASSERT_EQ(1, results.size());
00109   EXPECT_STREQ("Unity", results.front()->GetName().c_str());
00110 
00111   query = "/";
00112   results = GetIntrospectableNodesFromQuery(query, root_.get());
00113   ASSERT_EQ(1, results.size());
00114   EXPECT_STREQ("Unity", results.front()->GetName().c_str());
00115 
00116   query = "/Unity";
00117   results = GetIntrospectableNodesFromQuery(query, root_.get());
00118   ASSERT_EQ(1, results.size());
00119   EXPECT_STREQ("Unity", results.front()->GetName().c_str());
00120 }
00121 
00122 TEST_F(TestIntrospection, TestAsteriskWildcard)
00123 {
00124   std::list<Introspectable*> results;
00125   std::string query = "/Unity/*";
00126 
00127   results = GetIntrospectableNodesFromQuery(query, root_.get());
00128   ASSERT_EQ(2, results.size());
00129 
00130   for(auto p : results)
00131   {
00132     ASSERT_TRUE(
00133       p->GetName() == "DashController" ||
00134       p->GetName() == "PanelController"
00135       );
00136   }
00137 }
00138 
00139 TEST_F(TestIntrospection, TestRelativeAsteriskWildcard)
00140 {
00141   std::list<Introspectable*> results;
00142   std::string query = "//DashController/*";
00143 
00144   results = GetIntrospectableNodesFromQuery(query, root_.get());
00145   ASSERT_EQ(3, results.size());
00146 
00147   for(auto p : results)
00148   {
00149     ASSERT_TRUE(p->GetName() == "Foo");
00150   }
00151 }
00152 
00153 TEST_F(TestIntrospection, TestAbsoluteQueries)
00154 {
00155   std::list<Introspectable*> results;
00156   std::string query = "/Unity/DashController";
00157 
00158   results = GetIntrospectableNodesFromQuery(query, root_.get());
00159   ASSERT_EQ(1, results.size());
00160   EXPECT_STREQ("DashController", results.front()->GetName().c_str());
00161 }
00162 
00163 TEST_F(TestIntrospection, TestMalformedRelativeQueries)
00164 {
00165   std::list<Introspectable*> results;
00166   std::string query = "Unity";
00167 
00168   results = GetIntrospectableNodesFromQuery(query, root_.get());
00169   ASSERT_EQ(1, results.size());
00170   EXPECT_STREQ("Unity", results.front()->GetName().c_str());
00171 
00172   query = "Foo";
00173   results = GetIntrospectableNodesFromQuery(query, root_.get());
00174   ASSERT_EQ(3, results.size());
00175   for(auto p : results)
00176   {
00177     EXPECT_STREQ("Foo", p->GetName().c_str());
00178   }
00179 }
00180 
00181 TEST_F(TestIntrospection, TestSimpleRelativeQueries)
00182 {
00183   std::list<Introspectable*> results;
00184   std::string query = "//Unity";
00185 
00186   results = GetIntrospectableNodesFromQuery(query, root_.get());
00187   ASSERT_EQ(1, results.size());
00188   EXPECT_STREQ("Unity", results.front()->GetName().c_str());
00189 
00190   query = "//Foo";
00191   results = GetIntrospectableNodesFromQuery(query, root_.get());
00192   ASSERT_EQ(3, results.size());
00193   for(auto p : results)
00194   {
00195     EXPECT_STREQ("Foo", p->GetName().c_str());
00196   }
00197 }
00198 
00199 TEST_F(TestIntrospection, TestComplexRelativeQueries)
00200 {
00201   std::list<Introspectable*> results;
00202   std::string query = "//DashController/Foo";
00203 
00204   results = GetIntrospectableNodesFromQuery(query, root_.get());
00205   ASSERT_EQ(3, results.size());
00206   for(auto p : results)
00207   {
00208     EXPECT_STREQ("Foo", p->GetName().c_str());
00209   }
00210 }
00211 
00212 TEST_F(TestIntrospection, TestQueriesWithNoResults)
00213 {
00214   std::list<Introspectable*> results;
00215   std::string query = "//Does/Not/Exist";
00216 
00217   results = GetIntrospectableNodesFromQuery(query, root_.get());
00218   ASSERT_EQ(0, results.size());
00219 
00220   query = "DoesNotEverExist";
00221   results = GetIntrospectableNodesFromQuery(query, root_.get());
00222   ASSERT_EQ(0, results.size());
00223 
00224   query = "/Does/Not/Ever/Exist";
00225   results = GetIntrospectableNodesFromQuery(query, root_.get());
00226   ASSERT_EQ(0, results.size());
00227 }
00228 
00229 TEST_F(TestIntrospection, TestQueriesWithParams)
00230 {
00231   std::list<Introspectable*> results;
00232   // this should find our root node:
00233   results = GetIntrospectableNodesFromQuery("/Unity[SomeProperty=SomeValue]", root_.get());
00234   ASSERT_EQ(1, results.size());
00235   EXPECT_STREQ("Unity", results.front()->GetName().c_str());
00236   // but this should find nothing:
00237   results = GetIntrospectableNodesFromQuery("/Unity[SomeProperty=SomeOtherValue]", root_.get());
00238   ASSERT_EQ(0, results.size());
00239 
00240   // make sure relative paths work:
00241   results = GetIntrospectableNodesFromQuery("//Foo[Name=Foo]", root_.get());
00242   ASSERT_EQ(3, results.size());
00243   for(auto p : results)
00244   {
00245     EXPECT_STREQ("Foo", p->GetName().c_str());
00246   }
00247 
00248   // make sure param queries work with descendant nodes as well:
00249   results = GetIntrospectableNodesFromQuery("/Unity[SomeProperty=SomeValue]/DashController[Name=DashController]/Foo", root_.get());
00250   ASSERT_EQ(3, results.size());
00251   for(auto p : results)
00252   {
00253     EXPECT_STREQ("Foo", p->GetName().c_str());
00254   }
00255 }
00256 
00257 TEST_F(TestIntrospection, TestQueryTypeBool)
00258 {
00259   std::list<Introspectable*> results;
00260 
00261   // These are all equivilent and should return the root item and nothing more:
00262   std::list<std::string> queries = {"/Unity[BoolPropertyTrue=True]",
00263                                     "/Unity[BoolPropertyTrue=true]",
00264                                     "/Unity[BoolPropertyTrue=trUE]",
00265                                     "/Unity[BoolPropertyTrue=yes]",
00266                                     "/Unity[BoolPropertyTrue=ON]",
00267                                     "/Unity[BoolPropertyTrue=1]"};
00268 
00269   for(auto query : queries)
00270   {
00271     results = GetIntrospectableNodesFromQuery(query, root_.get());
00272     ASSERT_EQ(1, results.size());
00273     EXPECT_STREQ("Unity", results.front()->GetName().c_str());
00274   }
00275 
00276   // For boolean properties, anything that's not True, Yes, On or 1 is treated as false:
00277   queries = {"/Unity[BoolPropertyTrue=False]",
00278             "/Unity[BoolPropertyTrue=fAlSE]",
00279             "/Unity[BoolPropertyTrue=No]",
00280             "/Unity[BoolPropertyTrue=OFF]",
00281             "/Unity[BoolPropertyTrue=0]",
00282             "/Unity[BoolPropertyTrue=ThereWasAManFromNantucket]"};
00283   for(auto query : queries)
00284   {
00285     results = GetIntrospectableNodesFromQuery(query, root_.get());
00286     ASSERT_EQ(0, results.size());
00287   }
00288 }
00289 
00290 TEST_F(TestIntrospection, TestQueryTypeInt)
00291 {
00292   std::list<Introspectable*> results;
00293 
00294   // these should all select the root Unity node:
00295   std::list<std::string> queries = {"/Unity[BytePropertyPos=12]",
00296                                     "/Unity[Int16PropertyPos=1012]",
00297                                     "/Unity[Int16PropertyNeg=-1034]",
00298                                     "/Unity[UInt16PropertyPos=1056]",
00299                                     "/Unity[Int32PropertyPos=100012]",
00300                                     "/Unity[Int32PropertyNeg=-100034]",
00301                                     "/Unity[UInt32PropertyPos=100056]",
00302                                     "/Unity[Int64PropertyPos=100000012]",
00303                                     "/Unity[Int64PropertyNeg=-100000034]",
00304                                     "/Unity[UInt64PropertyPos=100000056]"};
00305   for(auto query : queries)
00306   {
00307     results = GetIntrospectableNodesFromQuery(query, root_.get());
00308     ASSERT_EQ(1, results.size()) << "Failing query: " << query;
00309     EXPECT_STREQ("Unity", results.front()->GetName().c_str());
00310   }
00311 
00312   // but these shouldn't:
00313   queries = {"/Unity[BytePropertyPos=1234]",
00314             "/Unity[Int16PropertyPos=0]",
00315             "/Unity[Int16PropertyNeg=-0]",
00316             "/Unity[Int16PropertyNeg=-]",
00317             "/Unity[UInt16PropertyPos=-1056]",
00318             "/Unity[Int32PropertyPos=999999999999999]",
00319             "/Unity[Int32PropertyNeg=Garbage]",
00320             "/Unity[UInt32PropertyPos=-23]"};
00321   for(auto query : queries)
00322   {
00323     results = GetIntrospectableNodesFromQuery(query, root_.get());
00324     ASSERT_EQ(0, results.size());
00325   }
00326 }
00327 
00328 TEST_F(TestIntrospection, TestMalformedQueries)
00329 {
00330   // this should work - we have not yet specified a parameter to test against.
00331   std::list<Introspectable*> results = GetIntrospectableNodesFromQuery("/Unity[", root_.get());
00332   ASSERT_EQ(1, results.size());
00333 
00334   std::list<std::string> queries = {"/Unity[BoolPropertyTrue",
00335                                   "/Unity[BoolPropertyTrue=",
00336                                   "/Unity[BoolPropertyTrue=]",
00337                                   "/Unity[BytePropertyPos=",
00338                                   "/Unity[BytePropertyPos=]",
00339                                   "/Unity[Int16PropertyPos=",
00340                                   "/Unity[Int16PropertyPos=]",
00341                                   "/Unity[Int16PropertyNeg=",
00342                                   "/Unity[Int16PropertyNeg=]",
00343                                   "/Unity[UInt16PropertyPos[=]]",
00344                                   "/Unity[Int32PropertyPos[[",
00345                                   "/Unity[Int32PropertyNeg]",
00346                                   "/Unity[UInt32PropertyPos=[",
00347                                   "/Unity[Int64PropertyPos[[",
00348                                   "/Unity[Int64PropertyNeg",
00349                                   "/Unity[UInt64PropertyPos]"};
00350 
00351   for (std::string query : queries)
00352   {
00353     results = GetIntrospectableNodesFromQuery(query, root_.get());
00354     ASSERT_EQ(0, results.size()) << "Failing query: " << query;
00355   }
00356 }