LCOV - code coverage report
Current view: top level - src/bindings/cpp/tests - testcpp_contextual_thread.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 273 279 97.8 %
Date: 2019-09-12 12:28:41 Functions: 34 49 69.4 %

          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 <kdbthread.hpp>
      10             : 
      11             : #include <kdbprivate.h>
      12             : 
      13             : #include <gtest/gtest.h>
      14             : 
      15             : using namespace kdb;
      16             : 
      17           2 : void foo1 (Coordinator & gc, KeySet & ks)
      18             : {
      19           4 :         Key specKey ("/hello", KEY_CASCADING_NAME, KEY_END);
      20             : 
      21           4 :         ThreadContext c1 (gc);
      22           6 :         ThreadValue<int> v1 (ks, c1, specKey);
      23           6 :         ASSERT_EQ (v1, 8);
      24          18 :         ASSERT_EQ (ks.lookup ("user/hello").getString (), "8");
      25             : 
      26           2 :         v1 = 5;
      27           6 :         ASSERT_EQ (v1, 5);
      28          18 :         ASSERT_EQ (ks.lookup ("user/hello").getString (), "5");
      29             : 
      30           4 :         std::this_thread::sleep_for (std::chrono::milliseconds (100));
      31           6 :         ASSERT_EQ (v1, 5);
      32             : }
      33             : 
      34           2 : void foo2 (Coordinator & gc, KeySet & ks)
      35             : {
      36           4 :         Key specKey ("/hello", KEY_CASCADING_NAME, KEY_END);
      37             : 
      38           4 :         ThreadContext c2 (gc);
      39           6 :         ThreadValue<int> v2 (ks, c2, specKey);
      40           6 :         ASSERT_EQ (v2, 5);
      41             : 
      42           4 :         std::this_thread::sleep_for (std::chrono::milliseconds (100));
      43           2 :         c2.syncLayers ();
      44           6 :         ASSERT_EQ (v2, 5);
      45             : 
      46           2 :         v2 = 12;
      47           6 :         ASSERT_EQ (v2, 12);
      48             : }
      49             : 
      50          20 : TEST (test_contextual_thread, instanciation)
      51             : {
      52           4 :         Key specKey ("/hello", KEY_CASCADING_NAME, KEY_END);
      53             : 
      54           4 :         KeySet ks;
      55           6 :         ks.append (Key ("user/hello", KEY_VALUE, "22", KEY_END));
      56             : 
      57           4 :         Coordinator gc;
      58           4 :         ThreadContext c (gc);
      59           6 :         ThreadValue<int> v (ks, c, specKey);
      60           6 :         ASSERT_EQ (v, 22);
      61          18 :         ASSERT_EQ (ks.lookup ("user/hello").getString (), "22");
      62             : 
      63           2 :         v = 8;
      64           6 :         ASSERT_EQ (v, 8);
      65          18 :         ASSERT_EQ (ks.lookup ("user/hello").getString (), "8");
      66             : 
      67           6 :         std::thread t1 (foo1, std::ref (gc), std::ref (ks));
      68             : 
      69           4 :         std::this_thread::sleep_for (std::chrono::milliseconds (50));
      70          18 :         ASSERT_EQ (ks.lookup ("user/hello").getString (), "5");
      71           2 :         c.syncLayers ();
      72          16 :         ASSERT_TRUE (ks.lookup ("user/hello"));
      73          18 :         ASSERT_EQ (ks.lookup ("user/hello").getString (), "5");
      74           8 :         ASSERT_EQ (v.getName (), "user/hello");
      75           8 :         ASSERT_EQ (ks.size (), 1);
      76           6 :         ASSERT_EQ (v, 5);
      77             : 
      78           6 :         std::thread t2 (foo2, std::ref (gc), std::ref (ks));
      79           2 :         t1.join ();
      80           2 :         t2.join ();
      81             : 
      82           2 :         c.syncLayers ();
      83           8 :         ASSERT_EQ (v.getName (), "user/hello");
      84          18 :         ASSERT_EQ (ks.lookup ("user/hello").getString (), "12");
      85           8 :         ASSERT_EQ (ks.size (), 1);
      86           6 :         ASSERT_EQ (v, 12);
      87             : }
      88             : 
      89          12 : class Other : public kdb::Layer
      90             : {
      91             : public:
      92          12 :         std::string id () const override
      93             :         {
      94          36 :                 return "other";
      95             :         }
      96           8 :         std::string operator() () const override
      97             :         {
      98          24 :                 return "notused";
      99             :         }
     100             : };
     101             : 
     102          36 : class Activate : public kdb::Layer
     103             : {
     104             : public:
     105         100 :         std::string id () const override
     106             :         {
     107         300 :                 return "activate";
     108             :         }
     109          58 :         std::string operator() () const override
     110             :         {
     111         174 :                 return "active";
     112             :         }
     113             : };
     114             : 
     115             : 
     116             : bool g_toggle = false;
     117             : 
     118           0 : void toggleOn ()
     119             : {
     120           2 :         g_toggle = true;
     121           0 : }
     122             : 
     123           0 : void toggleOff ()
     124             : {
     125           2 :         g_toggle = false;
     126           0 : }
     127             : 
     128           2 : void activate1 (Coordinator & gc, KeySet & ks)
     129             : {
     130           4 :         Key specKey ("/act/%activate%", KEY_CASCADING_NAME, KEY_END);
     131             : 
     132           4 :         ThreadContext c1 (gc);
     133           6 :         ThreadValue<int> v1 (ks, c1, specKey);
     134           6 :         gc.onLayerActivation<Activate> ([]() { toggleOn (); });
     135           6 :         gc.onLayerDeactivation<Activate> ([]() { toggleOff (); });
     136           6 :         ASSERT_EQ (v1, 10);
     137           4 :         c1.activate<Activate> ();
     138           4 :         ASSERT_TRUE (g_toggle);
     139           6 :         ASSERT_EQ (v1, 22);
     140           4 :         std::this_thread::sleep_for (std::chrono::milliseconds (200));
     141           6 :         ASSERT_EQ (v1, 22);
     142           4 :         c1.deactivate<Activate> ();
     143           6 :         ASSERT_FALSE (g_toggle);
     144           6 :         ASSERT_EQ (v1, 10);
     145             : }
     146             : 
     147             : #if defined(__APPLE__)
     148             : TEST (DISABLED_test_contextual_thread, activate)
     149             : #else
     150          20 : TEST (test_contextual_thread, activate)
     151             : #endif
     152             : {
     153           4 :         Key specKey ("/act/%activate%", KEY_CASCADING_NAME, KEY_END);
     154             : 
     155           4 :         KeySet ks;
     156           6 :         ks.append (Key ("user/act/%", KEY_VALUE, "10", KEY_END)); // not active layer
     157           6 :         ks.append (Key ("user/act/active", KEY_VALUE, "22", KEY_END));
     158             : 
     159           4 :         Coordinator gc;
     160           4 :         ThreadContext c (gc);
     161           6 :         ThreadValue<int> v (ks, c, specKey);
     162           6 :         ASSERT_EQ (v, 10);
     163           8 :         ASSERT_EQ (c.size (), 0);
     164          14 :         ASSERT_EQ (c["other"], "");
     165          14 :         ASSERT_EQ (c["activate"], "");
     166             : 
     167           6 :         std::thread t1 (activate1, std::ref (gc), std::ref (ks));
     168           6 :         ASSERT_EQ (v, 10);
     169           4 :         std::this_thread::sleep_for (std::chrono::milliseconds (100));
     170           4 :         ASSERT_TRUE (g_toggle);
     171           2 :         c.syncLayers ();
     172           6 :         ASSERT_EQ (v, 22);
     173           2 :         t1.join ();
     174           6 :         ASSERT_FALSE (g_toggle);
     175           6 :         ASSERT_EQ (v, 22);
     176           4 :         c.activate<Other> (); // also fetches updates
     177           8 :         ASSERT_EQ (c.size (), 1);
     178          14 :         ASSERT_EQ (c["other"], "notused");
     179          14 :         ASSERT_EQ (c["activate"], "");
     180           6 :         ASSERT_EQ (v, 10);
     181             : }
     182             : 
     183             : const uint32_t i_value = 55;
     184             : const char * s_value = "55";
     185             : 
     186          20 : TEST (test_contextual_thread, ThreadNoContext)
     187             : {
     188             :         using namespace kdb;
     189           4 :         KeySet ks;
     190           2 :         ThreadNoContext c;
     191           2 :         const char * name = "/%language%/%country%/%dialect%/test";
     192          18 :         ASSERT_TRUE (!ks.lookup (name));
     193           6 :         Value<int, ContextPolicyIs<ThreadNoContext>> i (ks, c, Key (name, KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
     194           4 :         ASSERT_EQ (i, i_value);
     195          16 :         ASSERT_TRUE (ks.lookup (name));
     196           2 :         i = 5;
     197           6 :         ASSERT_EQ (i, 5);
     198           8 :         ASSERT_EQ (i.getSpec ().getName (), name);
     199           2 :         i.syncKeySet ();
     200          18 :         ASSERT_EQ (ks.lookup (name).getString (), "5");
     201           2 :         i = 10;
     202           6 :         ASSERT_EQ (i, 10);
     203          18 :         ASSERT_EQ (ks.lookup (name).getString (), "10");
     204             : }
     205             : 
     206             : 
     207             : /**
     208             :  * @brief Dependent on layer Activate
     209             :  */
     210           8 : class Dep : public kdb::Layer
     211             : {
     212             : public:
     213           4 :         explicit Dep (ThreadValue<int> const & i) : m_i (std::to_string (static_cast<int> (i)))
     214             :         {
     215             :                 // capture current value of contextual value here
     216             :         }
     217          24 :         std::string id () const override
     218             :         {
     219          72 :                 return "dep";
     220             :         }
     221           8 :         std::string operator() () const override
     222             :         {
     223          16 :                 return m_i;
     224             :         }
     225             :         std::string m_i;
     226             : };
     227             : 
     228             : 
     229          20 : TEST (test_contextual_thread, activateNoDependency)
     230             : {
     231           4 :         Key specKey ("/act/%activate%", KEY_CASCADING_NAME, KEY_END);
     232             : 
     233           4 :         KeySet ks;
     234           6 :         ks.append (Key ("user/act/%", KEY_VALUE, "10", KEY_END)); // not active layer
     235           6 :         ks.append (Key ("user/act/active", KEY_VALUE, "22", KEY_END));
     236             : 
     237           4 :         Coordinator gc;
     238           4 :         ThreadContext c1 (gc);
     239           4 :         ThreadContext c2 (gc);
     240           6 :         ThreadValue<int> v (ks, c1, specKey);
     241           6 :         ASSERT_EQ (v, 10);
     242           8 :         ASSERT_EQ (c1.size (), 0);
     243          14 :         ASSERT_EQ (c1["other"], "");
     244          14 :         ASSERT_EQ (c1["activate"], "");
     245             : 
     246           4 :         c2.activate<Dep> (v);
     247           8 :         ASSERT_EQ (c2.size (), 1);
     248          14 :         ASSERT_EQ (c2["dep"], "10");
     249           4 :         c2.activate<Activate> ();
     250           8 :         ASSERT_EQ (c2.size (), 2);
     251          14 :         ASSERT_EQ (c2["dep"], "10");
     252          14 :         ASSERT_EQ (c2["activate"], "active");
     253             : 
     254           2 :         c1.syncLayers ();
     255          14 :         ASSERT_EQ (c1["dep"], "10");
     256          14 :         ASSERT_EQ (c2["activate"], "active");
     257           8 :         ASSERT_EQ (v.getName (), "user/act/active");
     258           6 :         ASSERT_EQ (v, 22);
     259             : }
     260             : 
     261             : 
     262          20 : TEST (test_contextual_thread, activateWithDependency)
     263             : {
     264           4 :         Key specKey ("/act/%activate%", KEY_CASCADING_NAME, KEY_END);
     265             : 
     266           4 :         KeySet ks;
     267           6 :         ks.append (Key ("user/act/%", KEY_VALUE, "10", KEY_END)); // not active layer
     268           6 :         ks.append (Key ("user/act/active", KEY_VALUE, "22", KEY_END));
     269             : 
     270           4 :         Coordinator gc;
     271           4 :         ThreadContext c1 (gc);
     272           4 :         ThreadContext c2 (gc);
     273           6 :         ThreadValue<int> v1 (ks, c1, specKey);
     274           6 :         ThreadValue<int> v2 (ks, c2, specKey);
     275           6 :         ASSERT_EQ (v1, 10);
     276           6 :         ASSERT_EQ (v2, 10);
     277             : 
     278           8 :         ASSERT_EQ (c1.size (), 0);
     279          14 :         ASSERT_EQ (c1["other"], "");
     280          14 :         ASSERT_EQ (c1["activate"], "");
     281             : 
     282           8 :         ASSERT_EQ (c2.size (), 0);
     283          14 :         ASSERT_EQ (c2["other"], "");
     284          14 :         ASSERT_EQ (c2["activate"], "");
     285             : 
     286           4 :         c2.activate<Activate> ();
     287           8 :         ASSERT_EQ (c2.size (), 1);
     288          14 :         ASSERT_EQ (c2["activate"], "active");
     289             : 
     290           6 :         ASSERT_EQ (v1, 10);
     291           6 :         ASSERT_EQ (v2, 22);
     292             : 
     293           4 :         c1.activate<Dep> (v1);
     294           8 :         ASSERT_EQ (c1.size (), 2);
     295          14 :         ASSERT_EQ (c1["dep"], "22") << "dependency not correct, activate does not do syncLayer";
     296          14 :         ASSERT_EQ (c1["activate"], "active");
     297          14 :         ASSERT_EQ (c2["activate"], "active");
     298             : }
     299             : 
     300           4 : class StrDep : public kdb::Layer
     301             : {
     302             : public:
     303           2 :         explicit StrDep (ThreadValue<std::string> const & i) : m_i (i)
     304             :         {
     305             :         }
     306          10 :         std::string id () const override
     307             :         {
     308          30 :                 return "dep";
     309             :         }
     310           0 :         std::string operator() () const override
     311             :         {
     312           0 :                 return m_i;
     313             :         }
     314             :         std::string m_i;
     315             : };
     316             : 
     317             : 
     318          20 : TEST (test_contextual_thread, activateWithDirectDependency)
     319             : {
     320           4 :         Key specKey ("/act/%activate%", KEY_END);
     321             : 
     322           4 :         KeySet ks;
     323           6 :         ks.append (Key ("user/act/%", KEY_VALUE, "inactive", KEY_END));
     324           6 :         ks.append (Key ("user/act/active", KEY_VALUE, "active", KEY_END));
     325             : 
     326           4 :         Coordinator gc;
     327           4 :         ThreadContext c1 (gc);
     328           4 :         ThreadContext c2 (gc);
     329           6 :         ThreadValue<std::string> v1 (ks, c1, specKey);
     330           6 :         ThreadValue<std::string> v2 (ks, c2, specKey);
     331           6 :         ThreadValue<std::string> vd (ks, c2, specKey);
     332           8 :         ASSERT_EQ (std::string (v1), "inactive");
     333           8 :         ASSERT_EQ (std::string (v2), "inactive");
     334           8 :         ASSERT_EQ (std::string (vd), "inactive");
     335             : 
     336           4 :         c1.activate<Activate> ();
     337           8 :         ASSERT_EQ (std::string (v1), "active");
     338           8 :         ASSERT_EQ (std::string (v2), "inactive");
     339           8 :         ASSERT_EQ (std::string (vd), "inactive");
     340             : 
     341           4 :         c2.activate<StrDep> (vd);
     342           8 :         ASSERT_EQ (std::string (v1), "active");
     343           8 :         ASSERT_EQ (std::string (v2), "active");
     344           8 :         ASSERT_EQ (std::string (vd), "active");
     345             : }
     346             : 
     347             : 
     348          20 : TEST (test_contextual_thread, syncInWith)
     349             : {
     350           4 :         Key specKey ("/act/%activate%", KEY_CASCADING_NAME, KEY_END);
     351             : 
     352           4 :         KeySet ks;
     353           6 :         ks.append (Key ("user/act/%", KEY_VALUE, "10", KEY_END)); // not active layer
     354           6 :         ks.append (Key ("user/act/active", KEY_VALUE, "22", KEY_END));
     355             : 
     356           4 :         Coordinator gc;
     357           4 :         ThreadContext c1 (gc);
     358           4 :         ThreadContext c2 (gc);
     359           6 :         ThreadValue<int> v (ks, c1, specKey);
     360           6 :         ASSERT_EQ (v, 10);
     361           8 :         ASSERT_EQ (c1.size (), 0);
     362          14 :         ASSERT_EQ (c1["other"], "");
     363          14 :         ASSERT_EQ (c1["activate"], "");
     364             : 
     365           4 :         c2.activate<Activate> ();
     366           8 :         ASSERT_EQ (c2.size (), 1);
     367          14 :         ASSERT_EQ (c2["activate"], "active");
     368             : 
     369           4 :         c1.with<Other> () ([&]() {
     370          20 :                 ASSERT_EQ (c1.size (), 1);
     371          16 :                 ASSERT_EQ (c1["other"], "notused");
     372          16 :                 ASSERT_EQ (c1["activate"], "");
     373          16 :                 ASSERT_EQ (v.getName (), "user/act/%");
     374           6 :                 ASSERT_EQ (v, 10);
     375             : 
     376           2 :                 c1.syncLayers ();
     377             : 
     378          10 :                 ASSERT_EQ (c1.size (), 2);
     379          16 :                 ASSERT_EQ (c1["other"], "notused");
     380          16 :                 ASSERT_EQ (c1["activate"], "active");
     381           8 :                 ASSERT_EQ (v.getName (), "user/act/active");
     382           6 :                 ASSERT_EQ (v, 22);
     383           8 :         });
     384             : 
     385           8 :         ASSERT_EQ (c1.size (), 1);
     386          14 :         ASSERT_EQ (c1["other"], "");
     387          14 :         ASSERT_EQ (c1["activate"], "active");
     388           8 :         ASSERT_EQ (v.getName (), "user/act/active");
     389           6 :         ASSERT_EQ (v, 22);
     390             : }
     391             : 
     392             : 
     393          20 : TEST (test_contextual_thread, syncBeforeWith)
     394             : {
     395           4 :         Key specKey ("/act/%activate%", KEY_CASCADING_NAME, KEY_END);
     396             : 
     397           4 :         KeySet ks;
     398           6 :         ks.append (Key ("user/act/%", KEY_VALUE, "10", KEY_END)); // not active layer
     399           6 :         ks.append (Key ("user/act/active", KEY_VALUE, "22", KEY_END));
     400             : 
     401           4 :         Coordinator gc;
     402           4 :         ThreadContext c1 (gc);
     403           4 :         ThreadContext c2 (gc);
     404           6 :         ThreadValue<int> v (ks, c1, specKey);
     405           6 :         ASSERT_EQ (v, 10);
     406           8 :         ASSERT_EQ (c1.size (), 0);
     407          14 :         ASSERT_EQ (c1["other"], "");
     408          14 :         ASSERT_EQ (c1["activate"], "");
     409             : 
     410           4 :         c2.activate<Activate> ();
     411           8 :         ASSERT_EQ (c2.size (), 1);
     412          14 :         ASSERT_EQ (c2["activate"], "active");
     413             : 
     414           2 :         c1.syncLayers ();
     415           8 :         ASSERT_EQ (c1.size (), 1);
     416          14 :         ASSERT_EQ (c1["other"], "");
     417          14 :         ASSERT_EQ (c1["activate"], "active");
     418           8 :         ASSERT_EQ (v.getName (), "user/act/active");
     419           6 :         ASSERT_EQ (v, 22);
     420             : 
     421           4 :         c1.with<Other> () ([&]() {
     422          12 :                 ASSERT_EQ (c1.size (), 2);
     423          16 :                 ASSERT_EQ (c1["other"], "notused");
     424          16 :                 ASSERT_EQ (c1["activate"], "active");
     425          12 :                 ASSERT_EQ (v.getName (), "user/act/active");
     426           6 :                 ASSERT_EQ (v, 22);
     427           8 :         });
     428             : 
     429           8 :         ASSERT_EQ (c1.size (), 1);
     430          14 :         ASSERT_EQ (c1["other"], "");
     431          14 :         ASSERT_EQ (c1["activate"], "active");
     432           8 :         ASSERT_EQ (v.getName (), "user/act/active");
     433           6 :         ASSERT_EQ (v, 22);
     434           6 : }

Generated by: LCOV version 1.13