LCOV - code coverage report
Current view: top level - src/bindings/cpp/tests - testcpp_contextual_basic.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 625 631 99.0 %
Date: 2019-09-12 12:28:41 Functions: 126 166 75.9 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include "kdbconfig.h"
      10             : 
      11             : #include <kdbcontext.hpp>
      12             : #include <kdbthread.hpp>
      13             : #include <kdbvalue.hpp>
      14             : 
      15             : #include <thread>
      16             : 
      17             : #include <gtest/gtest.h>
      18             : 
      19             : class TestValueSubject : public kdb::ValueSubject
      20             : {
      21           0 :         virtual void notifyInThread () override
      22             :         {
      23           0 :         }
      24             : };
      25             : 
      26           0 : void fooxx (kdb::Command &)
      27             : {
      28           0 : }
      29             : 
      30          20 : TEST (test_contextual_basic, command)
      31             : {
      32             :         using namespace kdb;
      33             : 
      34           2 :         TestValueSubject v;
      35           4 :         Key k;
      36          16 :         Command::Func f = [k]() -> Command::Pair { return Command::Pair ("", ""); };
      37             : 
      38           4 :         Command c (v, f);
      39             :         fooxx (c);
      40           4 :         c ();
      41           6 :         ASSERT_EQ (&f, &c.execute);
      42           6 :         ASSERT_EQ (&v, &c.v);
      43             : }
      44             : 
      45             : const uint32_t i_value = 55;
      46             : const char * s_value = "55";
      47             : 
      48          86 : class CountryGermanyLayer : public kdb::Layer
      49             : {
      50             : public:
      51          58 :         std::string id () const override
      52             :         {
      53         174 :                 return "country";
      54             :         }
      55          64 :         std::string operator() () const override
      56             :         {
      57         192 :                 return "germany";
      58             :         }
      59             : };
      60             : 
      61         118 : class LanguageGermanLayer : public kdb::Layer
      62             : {
      63             : public:
      64         128 :         std::string id () const override
      65             :         {
      66         384 :                 return "language";
      67             :         }
      68         118 :         std::string operator() () const override
      69             :         {
      70         354 :                 return "german";
      71             :         }
      72             : };
      73             : 
      74          16 : class CountryGPSLayer : public kdb::Layer
      75             : {
      76             : public:
      77          16 :         CountryGPSLayer () : m_country ("austria")
      78             :         {
      79             :         }
      80           8 :         std::string id () const override
      81             :         {
      82          24 :                 return "country";
      83             :         }
      84          10 :         std::string operator() () const override
      85             :         {
      86          20 :                 return m_country;
      87             :         }
      88             : 
      89             : private:
      90             :         std::string m_country;
      91             : };
      92             : 
      93           8 : class ThreadLayer : public kdb::Layer
      94             : {
      95             : public:
      96             :         ThreadLayer ()
      97           8 :         {
      98             :         }
      99           8 :         std::string id () const override
     100             :         {
     101          24 :                 return "thread";
     102             :         }
     103           8 :         std::string operator() () const override
     104             :         {
     105          16 :                 std::ostringstream os;
     106           8 :                 std::thread::id tid = std::this_thread::get_id ();
     107           8 :                 if (tid != g_main_id)
     108             :                 {
     109           4 :                         os << tid;
     110             :                 }
     111          16 :                 return os.str ();
     112             :         };
     113             : 
     114             : private:
     115             :         static const std::thread::id g_main_id;
     116             : };
     117             : 
     118           2 : const std::thread::id ThreadLayer::g_main_id = std::this_thread::get_id ();
     119             : 
     120          22 : class CountingLayer : public kdb::Layer
     121             : {
     122             : public:
     123          24 :         CountingLayer () : m_id ()
     124             :         {
     125             :         }
     126          44 :         std::string id () const override
     127             :         {
     128         132 :                 return "counting";
     129             :         }
     130          80 :         std::string operator() () const override
     131             :         {
     132         160 :                 std::ostringstream os;
     133         160 :                 os << m_id++;
     134         160 :                 return os.str ();
     135             :         };
     136             : 
     137             : private:
     138             :         mutable long long m_id;
     139             : };
     140             : 
     141             : 
     142          20 : class SelectedPrinterLayer : public kdb::Layer
     143             : {
     144             : public:
     145          10 :         std::string id () const override
     146             :         {
     147          30 :                 return "printer";
     148             :         }
     149          18 :         std::string operator() () const override
     150             :         {
     151          54 :                 return "Laserdrucker";
     152             :         }
     153             : };
     154             : 
     155          14 : class MainApplicationLayer : public kdb::Layer
     156             : {
     157             : public:
     158          22 :         std::string id () const override
     159             :         {
     160          66 :                 return "application";
     161             :         }
     162          96 :         std::string operator() () const override
     163             :         {
     164         288 :                 return "main";
     165             :         }
     166             : };
     167             : 
     168           4 : class ProfileLayer : public kdb::Layer
     169             : {
     170             : public:
     171           6 :         explicit ProfileLayer (kdb::String const & profile) : m_profile (profile)
     172             :         {
     173             :         }
     174          18 :         std::string id () const override
     175             :         {
     176          54 :                 return "profile";
     177             :         }
     178          72 :         std::string operator() () const override
     179             :         {
     180         144 :                 return m_profile;
     181             :         }
     182             : 
     183             : private:
     184             :         kdb::String const & m_profile;
     185             : };
     186             : 
     187             : template <typename T>
     188          54 : class test_contextual_basic : public ::testing::Test
     189             : {
     190             : public:
     191             :         T context;
     192             : };
     193             : 
     194             : template <>
     195          18 : class test_contextual_basic<kdb::ThreadContext> : public ::testing::Test
     196             : {
     197             : public:
     198          18 :         test_contextual_basic () : context (coordinator)
     199             :         {
     200          18 :         }
     201             :         static kdb::Coordinator coordinator;
     202             :         kdb::ThreadContext context;
     203             : };
     204             : 
     205           2 : kdb::Coordinator test_contextual_basic<kdb::ThreadContext>::coordinator{};
     206             : 
     207             : typedef ::testing::Types<kdb::Context, kdb::ThreadContext> myContextualPolicies;
     208             : TYPED_TEST_CASE (test_contextual_basic, myContextualPolicies);
     209             : 
     210          28 : TYPED_TEST (test_contextual_basic, integer)
     211             : {
     212             :         using namespace kdb;
     213           8 :         KeySet ks;
     214           8 :         TypeParam c = this->context;
     215          36 :         ASSERT_TRUE (!ks.lookup ("/%/%/%/test"));
     216             :         Value<int, ContextPolicyIs<TypeParam>> i (
     217          12 :                 ks, c, Key ("/%language%/%country%/%dialect%/test", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     218           8 :         ASSERT_EQ (i, i_value);
     219             :         // The value always needs a connection to a key
     220          32 :         ASSERT_TRUE (ks.lookup ("/%/%/%/test"));
     221           4 :         i = 5;
     222          12 :         ASSERT_EQ (i, 5);
     223          16 :         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     224           4 :         i.syncKeySet ();
     225          36 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "5");
     226          36 :         ASSERT_EQ (ks.lookup ("user/%/%/%/test").getString (), "5");
     227           4 :         i = 10;
     228          12 :         ASSERT_EQ (i, 10);
     229          36 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     230          16 :         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     231             : 
     232           8 :         c.template activate<LanguageGermanLayer> ();
     233           8 :         ASSERT_EQ (i, i_value);
     234             :         //{debug/ASSERT_TRUE}
     235          28 :         ASSERT_EQ (i.context ()["language"], "german");
     236          16 :         ASSERT_EQ (i.getName (), "/german/%/%/test");
     237             :         //{end}
     238          36 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     239          32 :         ASSERT_TRUE (ks.lookup ("/german/%/%/test"));
     240           4 :         i = 15;
     241          12 :         ASSERT_EQ (i, 15);
     242          36 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     243           4 :         i.syncKeySet ();
     244          36 :         ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     245             : 
     246           8 :         c.template deactivate<LanguageGermanLayer> ();
     247          12 :         ASSERT_EQ (i, 10);
     248          36 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     249          36 :         ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     250             : 
     251          20 :         c.template with<LanguageGermanLayer> () ([&]() {
     252          20 :                 ASSERT_EQ (i, 15);
     253          52 :                 ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     254          36 :                 ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     255          24 :                 c.template without<LanguageGermanLayer> () ([&]() {
     256          12 :                         ASSERT_EQ (i, 10);
     257          40 :                         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     258          36 :                         ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     259             :                 });
     260          12 :                 ASSERT_EQ (i, 15);
     261          36 :                 ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     262          36 :                 ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     263             :         });
     264          12 :         ASSERT_EQ (i, 10);
     265          36 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     266          36 :         ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     267             : 
     268          28 :         c.template with<LanguageGermanLayer> ().template with<CountryGermanyLayer> () ([&]() {
     269          24 :                 ASSERT_EQ (i, i_value);
     270          48 :                 ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     271          36 :                 ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     272          32 :                 ASSERT_TRUE (ks.lookup ("/german/germany/%/test"));
     273           4 :                 i = 20;
     274          16 :                 ASSERT_EQ (i.getName (), "user/german/germany/%/test");
     275          36 :                 ASSERT_EQ (ks.lookup ("/german/germany/%/test").getString (), "20");
     276             :                 /*
     277             :                 //{debug/backtrace}
     278             :                 #3  0x0000000000407a56 in operator() at first.cpp:1521
     279             :                         i = @0x7fffe36b69a0: { ...
     280             :                           m_evaluated_name = "/german/germany/%/test" }
     281             :                 //{end}
     282             :                 //{debug/breakpoint}
     283             :                 break 1520 if i.getName()
     284             :                               .compare("/german/germany/%/test") == 0
     285             :                 //{end}
     286             :                 */
     287          12 :                 ASSERT_EQ (i, 20);
     288             :         });
     289          12 :         ASSERT_EQ (i, 10);
     290          36 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     291          36 :         ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     292          36 :         ASSERT_EQ (ks.lookup ("/german/germany/%/test").getString (), "20");
     293             : 
     294          28 :         c.template with<LanguageGermanLayer> ().template with<CountryGermanyLayer> () ([&]() {
     295          20 :                 ASSERT_EQ (i, 20);
     296          48 :                 ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     297          36 :                 ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     298          36 :                 ASSERT_EQ (ks.lookup ("/german/germany/%/test").getString (), "20");
     299           4 :                 i = 30;
     300          12 :                 ASSERT_EQ (i, 30);
     301          36 :                 ASSERT_EQ (ks.lookup ("/german/germany/%/test").getString (), "30");
     302             :         });
     303          12 :         ASSERT_EQ (i, 10);
     304          36 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     305          36 :         ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     306          36 :         ASSERT_EQ (ks.lookup ("/german/germany/%/test").getString (), "30");
     307             : 
     308          24 :         c.template with<LanguageGermanLayer> ().template with<CountryGermanyLayer> () ([&]() {
     309          16 :                 ASSERT_EQ (i, 30);
     310          48 :                 ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     311          36 :                 ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     312          36 :                 ASSERT_EQ (ks.lookup ("/german/germany/%/test").getString (), "30");
     313          32 :                 c.template with<CountryGPSLayer> () ([&]() { ASSERT_EQ (i, i_value); });
     314          36 :                 ASSERT_EQ (ks.lookup ("/german/austria/%/test").getString (), s_value);
     315             :         });
     316          12 :         ASSERT_EQ (i, 10);
     317          36 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "10");
     318          36 :         ASSERT_EQ (ks.lookup ("/german/%/%/test").getString (), "15");
     319             : }
     320             : 
     321          28 : TYPED_TEST (test_contextual_basic, mixedWithActivate)
     322             : {
     323             :         using namespace kdb;
     324           8 :         KeySet ks;
     325           8 :         TypeParam c = this->context;
     326          36 :         ASSERT_TRUE (!ks.lookup ("/%/%/%/test"));
     327             :         Value<int, ContextPolicyIs<TypeParam>> i (
     328          12 :                 ks, c, Key ("/%language%/%country%/%dialect%/test", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     329           8 :         ASSERT_EQ (i, i_value);
     330             :         // The value always needs a connection to a key
     331          32 :         ASSERT_TRUE (ks.lookup ("/%/%/%/test"));
     332           4 :         i = 5;
     333          12 :         ASSERT_EQ (i, 5);
     334          16 :         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     335          36 :         ASSERT_EQ (ks.lookup ("user/%/%/%/test").getString (), "5");
     336             : 
     337           8 :         c.template activate<LanguageGermanLayer> ();
     338           4 :         i = 6;
     339          12 :         ASSERT_EQ (i, 6);
     340          16 :         ASSERT_EQ (i.getName (), "user/german/%/%/test");
     341          36 :         ASSERT_EQ (ks.lookup ("user/german/%/%/test").getString (), "6");
     342             : 
     343          24 :         c.template with<CountryGermanyLayer> () ([&]() {
     344          16 :                 i = 7;
     345          12 :                 ASSERT_EQ (i, 7);
     346          16 :                 ASSERT_EQ (i.getName (), "user/german/germany/%/test");
     347          36 :                 ASSERT_EQ (ks.lookup ("user/german/germany/%/test").getString (), "7");
     348             :         });
     349             : 
     350             :         // LanguageGermanLayer still active
     351          12 :         ASSERT_EQ (i, 6);
     352          16 :         ASSERT_EQ (i.getName (), "user/german/%/%/test");
     353          36 :         ASSERT_EQ (ks.lookup ("user/german/%/%/test").getString (), "6");
     354             : 
     355           8 :         c.template deactivate<LanguageGermanLayer> ();
     356          12 :         ASSERT_EQ (i, 5);
     357          16 :         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     358          36 :         ASSERT_EQ (ks.lookup ("user/%/%/%/test").getString (), "5");
     359             : }
     360             : 
     361          28 : TYPED_TEST (test_contextual_basic, nestedWithActivate)
     362             : {
     363             :         using namespace kdb;
     364           8 :         KeySet ks;
     365           8 :         TypeParam c = this->context;
     366          36 :         ASSERT_TRUE (!ks.lookup ("/%/%/%/test"));
     367             :         Value<int, ContextPolicyIs<TypeParam>> i (
     368          12 :                 ks, c, Key ("/%language%/%country%/%dialect%/test", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     369           8 :         ASSERT_EQ (i, i_value);
     370             :         // The value always needs a connection to a key
     371          32 :         ASSERT_TRUE (ks.lookup ("/%/%/%/test"));
     372           4 :         i = 5;
     373          12 :         ASSERT_EQ (i, 5);
     374          16 :         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     375          36 :         ASSERT_EQ (ks.lookup ("user/%/%/%/test").getString (), "5");
     376             : 
     377          20 :         c.template with<CountryGermanyLayer> () ([&]() {
     378          20 :                 i = 7;
     379          12 :                 ASSERT_EQ (i, 7);
     380          16 :                 ASSERT_EQ (i.getName (), "user/%/germany/%/test");
     381          40 :                 ASSERT_EQ (ks.lookup ("user/%/germany/%/test").getString (), "7");
     382             : 
     383          28 :                 c.template without<CountryGermanyLayer> () ([&]() {
     384           8 :                         c.template activate<LanguageGermanLayer> ();
     385             : 
     386          16 :                         i = 6;
     387          12 :                         ASSERT_EQ (i, 6);
     388          16 :                         ASSERT_EQ (i.getName (), "user/german/%/%/test");
     389          36 :                         ASSERT_EQ (ks.lookup ("user/german/%/%/test").getString (), "6");
     390             :                 });
     391             :         });
     392             : 
     393             :         // LanguageGermanLayer still active
     394          12 :         ASSERT_EQ (i, 6);
     395          16 :         ASSERT_EQ (i.getName (), "user/german/%/%/test");
     396          36 :         ASSERT_EQ (ks.lookup ("user/german/%/%/test").getString (), "6");
     397             : 
     398           8 :         c.template deactivate<LanguageGermanLayer> ();
     399          12 :         ASSERT_EQ (i, 5);
     400          16 :         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     401          36 :         ASSERT_EQ (ks.lookup ("user/%/%/%/test").getString (), "5");
     402             : }
     403             : 
     404             : 
     405          28 : TYPED_TEST (test_contextual_basic, nestedWithActivateConflicting)
     406             : {
     407             :         using namespace kdb;
     408           8 :         KeySet ks;
     409           8 :         TypeParam c = this->context;
     410          36 :         ASSERT_TRUE (!ks.lookup ("/%/%/%/test"));
     411             :         Value<int, ContextPolicyIs<TypeParam>> i (
     412          12 :                 ks, c, Key ("/%language%/%country%/%dialect%/test", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     413           8 :         ASSERT_EQ (i, i_value);
     414             :         // The value always needs a connection to a key
     415          32 :         ASSERT_TRUE (ks.lookup ("/%/%/%/test"));
     416           4 :         i = 5;
     417          12 :         ASSERT_EQ (i, 5);
     418          16 :         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     419          36 :         ASSERT_EQ (ks.lookup ("user/%/%/%/test").getString (), "5");
     420             : 
     421          20 :         c.template with<CountryGermanyLayer> () ([&]() {
     422          28 :                 i = 7;
     423          12 :                 ASSERT_EQ (i, 7);
     424          16 :                 ASSERT_EQ (i.getName (), "user/%/germany/%/test");
     425          44 :                 ASSERT_EQ (ks.lookup ("user/%/germany/%/test").getString (), "7");
     426             : 
     427          24 :                 c.template without<CountryGermanyLayer> () ([&]() {
     428          24 :                         ASSERT_EQ (i, 5);
     429          16 :                         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     430          40 :                         ASSERT_EQ (ks.lookup ("user/%/%/%/test").getString (), "5");
     431             : 
     432           8 :                         c.template activate<CountryGermanyLayer> ();
     433             : 
     434           4 :                         i = 6;
     435          12 :                         ASSERT_EQ (i, 6);
     436          16 :                         ASSERT_EQ (i.getName (), "user/%/germany/%/test");
     437          36 :                         ASSERT_EQ (ks.lookup ("user/%/germany/%/test").getString (), "6");
     438             :                 });
     439             :                 // restore activation of layer
     440             : 
     441          12 :                 ASSERT_EQ (i, 6);
     442          16 :                 ASSERT_EQ (i.getName (), "user/%/germany/%/test");
     443          36 :                 ASSERT_EQ (ks.lookup ("user/%/germany/%/test").getString (), "6");
     444             :         });
     445             :         // restore deactivation of layer (TODO: good idea in multi-thread setups if layer activation is pulled in? rather not..)
     446             : 
     447          12 :         ASSERT_EQ (i, 5);
     448          16 :         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     449          36 :         ASSERT_EQ (ks.lookup ("user/%/%/%/test").getString (), "5");
     450             : }
     451             : 
     452             : 
     453          28 : TYPED_TEST (test_contextual_basic, counting)
     454             : {
     455             :         using namespace kdb;
     456             : 
     457          12 :         std::shared_ptr<kdb::Layer> l = std::make_shared<CountingLayer> ();
     458           8 :         KeySet ks;
     459           8 :         TypeParam c = this->context;
     460          48 :         c.template with<CountingLayer> () ([&] { ASSERT_EQ (c["counting"], "0"); });
     461             :         // is it a specification error to have counting
     462             :         // two times?
     463             :         Value<int, ContextPolicyIs<TypeParam>> i (
     464          12 :                 ks, c, Key ("/%counting%/%counting%", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     465             : 
     466          16 :         ASSERT_EQ ((*l) (), "0");
     467          16 :         ASSERT_EQ ((*l) (), "1");
     468          20 :         c.withl (l, [&] {
     469          32 :                 ASSERT_EQ (c["counting"], "4");
     470          32 :                 ASSERT_EQ (c["counting"], "5");
     471             :         });
     472          16 :         ASSERT_EQ ((*l) (), "6");
     473          24 :         c.template with<CountingLayer> () ([&] {
     474          32 :                 ASSERT_EQ (c["counting"], "2");
     475          32 :                 ASSERT_EQ (c["counting"], "3");
     476             :         });
     477          32 :         ASSERT_TRUE (c["counting"].empty ());
     478          24 :         c.template with<CountingLayer> () ([&] {
     479          32 :                 ASSERT_EQ (c["counting"], "2");
     480          32 :                 ASSERT_EQ (c["counting"], "3");
     481             :         });
     482          32 :         ASSERT_TRUE (c["counting"].empty ());
     483           8 :         c.template activate<CountingLayer> ();
     484          28 :         ASSERT_EQ (c["counting"], "2");
     485          28 :         ASSERT_EQ (c["counting"], "3");
     486           8 :         c.template deactivate<CountingLayer> ();
     487          32 :         ASSERT_TRUE (c["counting"].empty ());
     488             : }
     489             : 
     490          28 : TYPED_TEST (test_contextual_basic, groups)
     491             : {
     492             :         using namespace kdb;
     493             : 
     494           8 :         KeySet ks;
     495           8 :         TypeParam c = this->context;
     496             :         Value<int, ContextPolicyIs<TypeParam>> i (
     497             :                 ks, c,
     498             :                 Key ("/%application%/%version profile thread module%/%manufacturer type family model%/serial_number", KEY_CASCADING_NAME,
     499          12 :                      KEY_META, "default", s_value, KEY_END));
     500          16 :         ASSERT_EQ (i.getName (), "/%/%/%/serial_number");
     501           8 :         c.template activate<MainApplicationLayer> ();
     502          12 :         String s (ks, c, Key ("/%x%", KEY_CASCADING_NAME, KEY_META, "default", "anonymous", KEY_END));
     503           8 :         c.template activate<ProfileLayer> (s);
     504          16 :         ASSERT_EQ (i.getName (), "/main/%/%/serial_number");
     505          32 :         c.activate ("version", "1");
     506          16 :         ASSERT_EQ (i.getName (), "/main/%1%anonymous/%/serial_number");
     507          32 :         c.activate ("module", "M1");
     508          16 :         ASSERT_EQ (i.getName (), "/main/%1%anonymous/%/serial_number");
     509          32 :         c.activate ("manufacturer", "hp");
     510          16 :         ASSERT_EQ (i.getName (), "/main/%1%anonymous/%hp/serial_number");
     511          32 :         c.activate ("family", "EliteBook");
     512          16 :         ASSERT_EQ (i.getName (), "/main/%1%anonymous/%hp/serial_number");
     513           8 :         c.template activate<KeyValueLayer> ("type", "MobileWorkstation");
     514          16 :         ASSERT_EQ (i.getName (), "/main/%1%anonymous/%hp%MobileWorkstation%EliteBook/serial_number");
     515           8 :         c.template activate<KeyValueLayer> ("model", "8570");
     516          16 :         ASSERT_EQ (i.getName (), "/main/%1%anonymous/%hp%MobileWorkstation%EliteBook%8570/serial_number");
     517           8 :         c.template activate<KeyValueLayer> ("thread", "40");
     518          16 :         ASSERT_EQ (i.getName (), "/main/%1%anonymous%40%M1/%hp%MobileWorkstation%EliteBook%8570/serial_number");
     519           8 :         c.template deactivate<KeyValueLayer> ("version", "");
     520          16 :         ASSERT_EQ (i.getName (), "/main/%/%hp%MobileWorkstation%EliteBook%8570/serial_number");
     521           8 :         c.template activate<KeyValueLayer> ("version", "4");
     522          16 :         ASSERT_EQ (i.getName (), "/main/%4%anonymous%40%M1/%hp%MobileWorkstation%EliteBook%8570/serial_number");
     523           8 :         c.template deactivate<KeyValueLayer> ("manufacturer", "");
     524          16 :         ASSERT_EQ (i.getName (), "/main/%4%anonymous%40%M1/%/serial_number");
     525           8 :         c.template activate<KeyValueLayer> ("manufacturer", "HP");
     526          16 :         ASSERT_EQ (i.getName (), "/main/%4%anonymous%40%M1/%HP%MobileWorkstation%EliteBook%8570/serial_number");
     527           8 :         c.template deactivate<KeyValueLayer> ("type", "");
     528          16 :         ASSERT_EQ (i.getName (), "/main/%4%anonymous%40%M1/%HP/serial_number");
     529          24 :         c.template with<KeyValueLayer> ("type", "Notebook") ([&] {
     530          24 :                 ASSERT_EQ (i.getName (), "/main/%4%anonymous%40%M1/%HP%Notebook%EliteBook%8570/serial_number");
     531           8 :                 c.template without<KeyValueLayer> ("type",
     532          38 :                                                    "") ([&] { ASSERT_EQ (i.getName (), "/main/%4%anonymous%40%M1/%HP/serial_number"); });
     533          16 :                 ASSERT_EQ (i.getName (), "/main/%4%anonymous%40%M1/%HP%Notebook%EliteBook%8570/serial_number");
     534             :         });
     535             : }
     536             : 
     537           8 : class myId : public kdb::Wrapped
     538             : {
     539          14 :         virtual std::string layerId () const
     540             :         {
     541          42 :                 return "id";
     542             :         }
     543             : 
     544           4 :         virtual std::string layerVal () const
     545             :         {
     546          12 :                 return "my";
     547             :         }
     548             : };
     549             : 
     550             : 
     551          28 : TYPED_TEST (test_contextual_basic, wrapped)
     552             : {
     553             :         using namespace kdb;
     554             : 
     555           8 :         KeySet ks;
     556           8 :         TypeParam c = this->context;
     557          12 :         Value<int, ContextPolicyIs<TypeParam>> i (ks, c, Key ("/%id%/key", KEY_META, "default", s_value, KEY_END));
     558          12 :         ASSERT_EQ (i.getName (), "/%/key");
     559          16 :         c.activate (myId ());
     560          16 :         ASSERT_EQ (i.getName (), "/my/key");
     561             : }
     562             : 
     563             : 
     564          28 : TYPED_TEST (test_contextual_basic, cvWrapped)
     565             : {
     566             :         using namespace kdb;
     567             : 
     568           8 :         KeySet ks;
     569           8 :         TypeParam c = this->context;
     570          12 :         Value<std::string, ContextPolicyIs<TypeParam>> i (ks, c, Key ("/ignore/id", KEY_META, "default", "my", KEY_END));
     571             : 
     572          12 :         Value<int, ContextPolicyIs<TypeParam>> x (ks, c, Key ("/%id%/key", KEY_META, "default", s_value, KEY_END));
     573             : 
     574          16 :         ASSERT_EQ (x.getName (), "/%/key");
     575          32 :         ASSERT_TRUE (ks.lookup ("/%/key"));
     576           8 :         c.activate (i);
     577          16 :         ASSERT_EQ (x.getName (), "/my/key");
     578          32 :         ASSERT_TRUE (ks.lookup ("/my/key"));
     579             : 
     580          12 :         ks.append (Key ("/other/key", KEY_VALUE, "88", KEY_END));
     581          20 :         i = "other";
     582           8 :         c.activate (i);
     583          16 :         ASSERT_EQ (x.getName (), "/other/key");
     584          32 :         ASSERT_TRUE (ks.lookup ("/other/key"));
     585          12 :         ASSERT_EQ (x, 88);
     586          36 :         ASSERT_EQ (ks.lookup ("/other/key").getString (), "88");
     587             : 
     588          12 :         ks.append (Key ("/other/key", KEY_VALUE, "100", KEY_END));
     589          36 :         ASSERT_EQ (ks.lookup ("/other/key").getString (), "100");
     590          12 :         ASSERT_EQ (x, 88) << "updated from KeySet?";
     591             : }
     592             : 
     593             : 
     594          28 : TYPED_TEST (test_contextual_basic, cvWrappedInt)
     595             : {
     596             :         using namespace kdb;
     597             : 
     598           8 :         KeySet ks;
     599           8 :         TypeParam c = this->context;
     600          12 :         Value<int, ContextPolicyIs<TypeParam>> i (ks, c, Key ("/ignore/id", KEY_META, "default", "88", KEY_END));
     601             : 
     602          12 :         Value<int, ContextPolicyIs<TypeParam>> x (ks, c, Key ("/%id%/key", KEY_META, "default", s_value, KEY_END));
     603             : 
     604          16 :         ASSERT_EQ (x.getName (), "/%/key");
     605           8 :         c.activate (i);
     606          16 :         ASSERT_EQ (x.getName (), "/88/key");
     607             : }
     608             : 
     609             : 
     610          20 : TEST (test_contextual_basic, integer_copy)
     611             : {
     612             :         using namespace kdb;
     613           4 :         KeySet ks;
     614           4 :         Context c;
     615          18 :         ASSERT_TRUE (!ks.lookup ("/%/%/%/test"));
     616           6 :         Integer i (ks, c, Key ("/%language%/%country%/%dialect%/test", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     617           4 :         ASSERT_EQ (i, i_value);
     618          16 :         ASSERT_TRUE (ks.lookup ("/%/%/%/test"));
     619           2 :         i = 5;
     620           6 :         ASSERT_EQ (i, 5);
     621           8 :         ASSERT_EQ (i.getName (), "user/%/%/%/test");
     622           2 :         i.syncKeySet ();
     623          18 :         ASSERT_EQ (ks.lookup ("/%/%/%/test").getString (), "5");
     624             : }
     625             : 
     626          20 : TEST (test_contextual_basic, evaluate)
     627             : {
     628             :         using namespace kdb;
     629           4 :         kdb::Context c;
     630          14 :         ASSERT_EQ (c["language"], "");
     631          14 :         ASSERT_EQ (c["country"], "");
     632          14 :         ASSERT_EQ (c["dialect"], "");
     633          14 :         ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/%/%/%/test");
     634          14 :         ASSERT_EQ (c.evaluate ("/%language country dialect%/test"), "/%/test");
     635             : 
     636           4 :         c.activate<LanguageGermanLayer> ();
     637          14 :         ASSERT_EQ (c["language"], "german");
     638          14 :         ASSERT_EQ (c["country"], "");
     639          14 :         ASSERT_EQ (c["dialect"], "");
     640          14 :         ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/%/%/test");
     641          14 :         ASSERT_EQ (c.evaluate ("/%language country dialect%/test"), "/%german/test");
     642             : 
     643           4 :         c.activate<LanguageGermanLayer> ();
     644           4 :         c.activate<CountryGermanyLayer> ();
     645          14 :         ASSERT_EQ (c["language"], "german");
     646          14 :         ASSERT_EQ (c["country"], "germany");
     647          14 :         ASSERT_EQ (c["dialect"], "");
     648          14 :         ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/germany/%/test");
     649          14 :         ASSERT_EQ (c.evaluate ("/%language country dialect%/test"), "/%german%germany/test");
     650           4 :         c.deactivate<CountryGermanyLayer> ();
     651             : 
     652           4 :         c.activate<LanguageGermanLayer> ();
     653           4 :         c.activate<KeyValueLayer> ("country", "%");
     654          14 :         ASSERT_EQ (c["language"], "german");
     655          14 :         ASSERT_EQ (c["country"], "%");
     656          14 :         ASSERT_EQ (c["dialect"], "");
     657             :         // TODO: Escaping not implemented
     658             :         // ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/\\%/%/test");
     659             :         // ASSERT_EQ (c.evaluate ("/%language country dialect%/test"), "/%german%\\%/test");
     660           4 :         c.deactivate<KeyValueLayer> ("country", "%");
     661             : 
     662           4 :         c.deactivate<LanguageGermanLayer> ();
     663          14 :         ASSERT_EQ (c["language"], "");
     664          14 :         ASSERT_EQ (c["country"], "");
     665          14 :         ASSERT_EQ (c["dialect"], "");
     666          14 :         ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/%/%/%/test");
     667             : 
     668           4 :         c.with<LanguageGermanLayer> () ([&]() {
     669          32 :                 ASSERT_EQ (c["language"], "german");
     670          16 :                 ASSERT_EQ (c["country"], "");
     671          16 :                 ASSERT_EQ (c["dialect"], "");
     672          16 :                 ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/%/%/test");
     673           4 :                 c.without<LanguageGermanLayer> () ([&]() {
     674          20 :                         ASSERT_EQ (c["language"], "");
     675          16 :                         ASSERT_EQ (c["country"], "");
     676          16 :                         ASSERT_EQ (c["dialect"], "");
     677          16 :                         ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/%/%/%/test");
     678           8 :                 });
     679          16 :                 ASSERT_EQ (c["language"], "german");
     680          16 :                 ASSERT_EQ (c["country"], "");
     681          16 :                 ASSERT_EQ (c["dialect"], "");
     682          16 :                 ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/%/%/test");
     683           8 :         });
     684          14 :         ASSERT_EQ (c["language"], "");
     685          14 :         ASSERT_EQ (c["country"], "");
     686          14 :         ASSERT_EQ (c["dialect"], "");
     687          14 :         ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/%/%/%/test");
     688             : 
     689           6 :         c.with<LanguageGermanLayer> ().with<CountryGermanyLayer> () ([&]() {
     690          38 :                 ASSERT_EQ (c["language"], "german");
     691          16 :                 ASSERT_EQ (c["country"], "germany");
     692          16 :                 ASSERT_EQ (c["dialect"], "");
     693           8 :                 ASSERT_EQ (c.size (), 2);
     694          16 :                 ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/germany/%/test");
     695          16 :                 ASSERT_EQ (c.evaluate ("/%language country dialect%/test"), "/%german%germany/test");
     696           4 :                 c.with<CountryGPSLayer> () ([&]() {
     697          26 :                         ASSERT_EQ (c["language"], "german");
     698          16 :                         ASSERT_EQ (c["country"], "austria");
     699          16 :                         ASSERT_EQ (c["dialect"], "");
     700          16 :                         ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/austria/%/test");
     701          16 :                         ASSERT_EQ (c.evaluate ("/%language country dialect%/test"), "/%german%austria/test");
     702           4 :                         c.without<CountryGPSLayer> () ([&]() {
     703          20 :                                 ASSERT_EQ (c["language"], "german");
     704          16 :                                 ASSERT_EQ (c["country"], "");
     705          16 :                                 ASSERT_EQ (c["dialect"], "");
     706          16 :                                 ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/%/%/test");
     707           8 :                         });
     708           8 :                 });
     709          16 :                 ASSERT_EQ (c["language"], "german");
     710          16 :                 ASSERT_EQ (c["country"], "germany");
     711          16 :                 ASSERT_EQ (c["dialect"], "");
     712          16 :                 ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/germany/%/test");
     713          16 :                 ASSERT_EQ (c.evaluate ("/%language country%/%dialect%/test"), "/%german%germany/%/test");
     714           8 :         });
     715          14 :         ASSERT_EQ (c["language"], "");
     716          14 :         ASSERT_EQ (c["country"], "");
     717          14 :         ASSERT_EQ (c["dialect"], "");
     718          14 :         ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/%/%/%/test");
     719             : 
     720           6 :         c.with<LanguageGermanLayer> ().with<CountryGermanyLayer> () ([&] {
     721          26 :                 ASSERT_EQ (c["language"], "german");
     722          16 :                 ASSERT_EQ (c["country"], "germany");
     723          16 :                 ASSERT_EQ (c["dialect"], "");
     724          16 :                 ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/german/germany/%/test");
     725          16 :                 ASSERT_EQ (c.evaluate ("/%language%/%language%/%dialect%/test"), "/german/german/%/test");
     726             : 
     727          16 :                 ASSERT_EQ (c.evaluate ("/%language%%country%%dialect%/test"), "/germangermany%/test");
     728          16 :                 ASSERT_EQ (c.evaluate ("/%language%%language%%dialect%/test"), "/germangerman%/test");
     729           8 :         });
     730          14 :         ASSERT_EQ (c["language"], "");
     731          14 :         ASSERT_EQ (c["country"], "");
     732          14 :         ASSERT_EQ (c["dialect"], "");
     733          14 :         ASSERT_EQ (c.evaluate ("/%language%/%country%/%dialect%/test"), "/%/%/%/test");
     734             : 
     735          14 :         ASSERT_EQ (c["language"], "");
     736          14 :         ASSERT_EQ (c["country"], "");
     737          14 :         ASSERT_EQ (c["dialect"], "");
     738          14 :         ASSERT_EQ (c.evaluate ("/%language%%country%%dialect%/test"), "/%%%/test");
     739             : 
     740           4 :         KeySet ks;
     741             :         Integer i (ks, c,
     742           4 :                    Key ("/%application%/%version%/%profile%/%thread%/%module%/%manufacturer%/%type%/%family%/%model%/serial_number",
     743           6 :                         KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     744             :         Integer j (ks, c,
     745           4 :                    Key ("/%application version profile thread module manufacturer type family model%/serial_number", KEY_CASCADING_NAME,
     746           6 :                         KEY_META, "default", s_value, KEY_END));
     747           8 :         ASSERT_EQ (i.getName (), "/%/%/%/%/%/%/%/%/%/serial_number");
     748           8 :         ASSERT_EQ (j.getName (), "/%/serial_number");
     749           4 :         c.activate<MainApplicationLayer> ();
     750           8 :         ASSERT_EQ (i.getName (), "/main/%/%/%/%/%/%/%/%/serial_number");
     751           8 :         ASSERT_EQ (j.getName (), "/%main/serial_number");
     752           6 :         String s (ks, c, Key ("/%x%", KEY_CASCADING_NAME, KEY_META, "default", "anonymous", KEY_END));
     753           4 :         c.activate<ProfileLayer> (s);
     754           8 :         ASSERT_EQ (i.getName (), "/main/%/anonymous/%/%/%/%/%/%/serial_number");
     755           8 :         ASSERT_EQ (j.getName (), "/%main/serial_number");
     756           4 :         c.activate<KeyValueLayer> ("module", "M1");
     757           8 :         ASSERT_EQ (i.getName (), "/main/%/anonymous/%/M1/%/%/%/%/serial_number");
     758           8 :         ASSERT_EQ (j.getName (), "/%main/serial_number");
     759           4 :         c.activate<KeyValueLayer> ("manufacturer", "hp");
     760           8 :         ASSERT_EQ (i.getName (), "/main/%/anonymous/%/M1/hp/%/%/%/serial_number");
     761           8 :         ASSERT_EQ (j.getName (), "/%main/serial_number");
     762           4 :         c.activate<KeyValueLayer> ("family", "EliteBook");
     763           8 :         ASSERT_EQ (i.getName (), "/main/%/anonymous/%/M1/hp/%/EliteBook/%/serial_number");
     764           8 :         ASSERT_EQ (j.getName (), "/%main/serial_number");
     765           4 :         c.activate<KeyValueLayer> ("version", "1");
     766           8 :         ASSERT_EQ (i.getName (), "/main/1/anonymous/%/M1/hp/%/EliteBook/%/serial_number");
     767           8 :         ASSERT_EQ (j.getName (), "/%main%1%anonymous/serial_number");
     768             : }
     769             : 
     770             : 
     771           6 : struct MockObserver : kdb::ValueObserver
     772             : {
     773           6 :         MockObserver () : counter ()
     774             :         {
     775             :         }
     776             : 
     777          22 :         virtual void updateContext (bool) const override
     778             :         {
     779          22 :                 ++counter;
     780          22 :         }
     781             : 
     782           0 :         virtual kdb::Key getDepKey () const override
     783             :         {
     784           0 :                 throw "should not happen";
     785             :         }
     786             : 
     787             :         mutable long long counter;
     788             : };
     789             : 
     790             : // duplicates need to be filtered
     791          20 : TEST (test_contextual_basic, valueObserver)
     792             : {
     793           4 :         kdb::Context c;
     794           4 :         MockObserver o1;
     795           4 :         MockObserver o2;
     796           4 :         MockObserver o3;
     797           8 :         c.attachByName ("/%event1%/%event2%", o1);
     798           8 :         c.attachByName ("/%event1%/%event3%", o2);
     799           8 :         c.attachByName ("/%eventX%", o3);
     800           8 :         c.attachByName ("/%eventX%", o3);
     801           6 :         ASSERT_EQ (o1.counter, 0);
     802           6 :         ASSERT_EQ (o2.counter, 0);
     803          12 :         c.notifyByEvents ({ "event1" });
     804           6 :         ASSERT_EQ (o1.counter, 1);
     805           6 :         ASSERT_EQ (o2.counter, 1);
     806          12 :         c.notifyByEvents ({ "event2" });
     807           6 :         ASSERT_EQ (o1.counter, 2);
     808           6 :         ASSERT_EQ (o2.counter, 1);
     809          12 :         c.notifyByEvents ({ "event3" });
     810           6 :         ASSERT_EQ (o1.counter, 2);
     811           6 :         ASSERT_EQ (o2.counter, 2);
     812          12 :         c.notifyByEvents ({ "event4" });
     813           6 :         ASSERT_EQ (o1.counter, 2);
     814           6 :         ASSERT_EQ (o2.counter, 2);
     815          16 :         c.notifyByEvents ({ "event1", "event2" });
     816           6 :         ASSERT_EQ (o1.counter, 3);
     817           6 :         ASSERT_EQ (o2.counter, 3);
     818          16 :         c.notifyByEvents ({ "event1", "event3" });
     819           6 :         ASSERT_EQ (o1.counter, 4);
     820           6 :         ASSERT_EQ (o2.counter, 4);
     821           6 :         ASSERT_EQ (o3.counter, 0);
     822           2 :         c.notifyAllEvents ();
     823           6 :         ASSERT_EQ (o1.counter, 5);
     824           6 :         ASSERT_EQ (o2.counter, 5);
     825           6 :         ASSERT_EQ (o3.counter, 1);
     826             : }
     827             : 
     828             : 
     829             : bool fooFirst = true;
     830             : 
     831             : //{foo}
     832           6 : void foo (kdb::Integer & e)
     833             : {
     834          18 :         e.context ().with<SelectedPrinterLayer> () ([&]() {
     835           6 :                 if (fooFirst)
     836          22 :                         ASSERT_EQ (e, i_value);
     837             :                 else
     838          12 :                         ASSERT_EQ (e, 20);
     839           6 :                 e = 20;
     840          18 :                 ASSERT_EQ (e, 20);
     841          24 :         });
     842          18 :         ASSERT_EQ (e, 12);
     843           6 :         fooFirst = false;
     844             : }
     845             : //{end}
     846             : 
     847             : bool barFirst = true;
     848             : 
     849           4 : void bar (kdb::Integer const & e)
     850             : {
     851          16 :         e.context ().with<ThreadLayer> ().with<SelectedPrinterLayer> () ([&]() {
     852           4 :                 if (barFirst)
     853          10 :                         ASSERT_EQ (e, 20);
     854             :                 else
     855           4 :                         ASSERT_EQ (e, i_value);
     856             : 
     857          32 :                 e.context ().without<ThreadLayer> () ([&]() { ASSERT_EQ (e, 20); });
     858          16 :         });
     859          12 :         ASSERT_EQ (e, 12);
     860           4 :         barFirst = false;
     861             : }
     862             : 
     863          20 : TEST (test_contextual_basic, threads)
     864             : {
     865             :         using namespace kdb;
     866             : 
     867           4 :         KeySet ks;
     868           4 :         Context c;
     869           6 :         kdb::Integer n (ks, c, Key ("/%thread%/%printer%/test", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     870             : 
     871             : 
     872           4 :         n.context ().activate<MainApplicationLayer> ();
     873           4 :         ASSERT_EQ (n, i_value);
     874             : 
     875           2 :         n = 18;
     876           6 :         ASSERT_EQ (n, 18);
     877             : 
     878           2 :         Integer & d = n;
     879             : 
     880           2 :         d = i_value;
     881           4 :         ASSERT_EQ (d, i_value);
     882             : 
     883           2 :         d = 12;
     884           6 :         ASSERT_EQ (d, 12);
     885             : 
     886           2 :         foo (d);
     887           6 :         ASSERT_EQ (d, 12);
     888             : 
     889           2 :         foo (d);
     890           6 :         ASSERT_EQ (d, 12);
     891             : 
     892           2 :         bar (d);
     893           6 :         ASSERT_EQ (d, 12);
     894             : 
     895           4 :         std::thread t1 (bar, std::cref (d));
     896           2 :         t1.join ();
     897           6 :         ASSERT_EQ (d, 12);
     898             : 
     899           4 :         std::thread t2 (foo, std::ref (d));
     900           2 :         t2.join ();
     901           6 :         ASSERT_EQ (d, 12);
     902             : }
     903             : 
     904          20 : TEST (test_contextual_basic, nocontext)
     905             : {
     906             :         using namespace kdb;
     907           4 :         KeySet ks;
     908             :         NoContext c;
     909           6 :         kdb::Value<int> n (ks, c, Key ("/test", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     910           4 :         ASSERT_EQ (n, i_value);
     911             : 
     912           2 :         n = 18;
     913           6 :         ASSERT_EQ (n, 18);
     914             : }
     915             : 
     916          20 : TEST (test_contextual_basic, operators)
     917             : {
     918             :         using namespace kdb;
     919           4 :         KeySet ks;
     920             :         NoContext c;
     921           6 :         kdb::Value<int> n (ks, c, Key ("/test/n", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     922           6 :         kdb::Value<int> m (ks, c, Key ("/test/m", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     923           4 :         ASSERT_EQ (n, i_value);
     924           4 :         ASSERT_EQ (m, i_value);
     925             : 
     926           2 :         n = 18;
     927           6 :         ASSERT_EQ (n, 18);
     928           6 :         ASSERT_EQ (18, n);
     929           4 :         ASSERT_EQ (n, n);
     930           8 :         ASSERT_EQ (!n, 0);
     931           8 :         ASSERT_EQ (0, !n);
     932           8 :         ASSERT_EQ (~n, ~18);
     933           8 :         ASSERT_EQ (~18, ~n);
     934             : 
     935           4 :         ASSERT_NE (n, 19);
     936           4 :         ASSERT_NE (19, n);
     937           6 :         ASSERT_NE (!n, n);
     938           6 :         ASSERT_NE (~n, n);
     939             : 
     940           4 :         ASSERT_LT (n, 19);
     941           4 :         ASSERT_GT (n, 17);
     942           4 :         ASSERT_LE (n, 19);
     943           4 :         ASSERT_GE (n, 17);
     944             : 
     945           4 :         ASSERT_LE (n, 18);
     946           4 :         ASSERT_GE (n, 18);
     947             : 
     948           2 :         n = 18;
     949           2 :         m = 18;
     950             : 
     951           4 :         ASSERT_EQ (n, m);
     952           4 :         ASSERT_EQ (m, n);
     953             : 
     954           4 :         n += 3;
     955           4 :         m += 3;
     956             : 
     957           4 :         ASSERT_EQ (n, m);
     958           4 :         ASSERT_EQ (m, n);
     959             : 
     960           4 :         m += n;
     961           6 :         ASSERT_EQ (n, 21);
     962           6 :         ASSERT_EQ (m, 42);
     963             : 
     964           6 :         ASSERT_EQ (n + n, m);
     965           6 :         ASSERT_EQ (m, n + n);
     966             : 
     967           2 :         --n;
     968           6 :         ASSERT_EQ (n, 20);
     969             : 
     970           6 :         ASSERT_EQ (n && n, true);
     971             : 
     972           4 :         n -= 10;
     973           6 :         ASSERT_EQ (n, 10);
     974             : 
     975           4 :         n *= 2;
     976           6 :         ASSERT_EQ (n, 20);
     977             : 
     978           4 :         n /= 2;
     979           6 :         ASSERT_EQ (n, 10);
     980             : 
     981           4 :         n %= 12;
     982           6 :         ASSERT_EQ (n, 10 % 12);
     983             : 
     984           2 :         n = 4 | 8;
     985           4 :         n |= 16;
     986           6 :         ASSERT_EQ (n, 4 | 8 | 16);
     987             : 
     988           2 :         n = 8;
     989           2 :         n = *&n; // *& added to suppress clang warning
     990           2 :         m = n;
     991           6 :         ASSERT_EQ (n, 8);
     992           6 :         ASSERT_EQ (m, 8);
     993           6 :         ASSERT_EQ (8, n);
     994           6 :         ASSERT_EQ (8, m);
     995             : 
     996           2 :         n = -8;
     997           2 :         m = 8;
     998           8 :         ASSERT_EQ (n, -m);
     999           8 :         ASSERT_EQ (-n, m);
    1000           6 : }

Generated by: LCOV version 1.13