TEST(type, version) { try { KeySet config; config.append( Key("system/require_version", KEY_VALUE, "3", KEY_END) ); TypeChecker tc(config); succeed_if (false, "version should not match"); } catch (const char *text) { succeed_if (true, "version should not match"); succeed_if (!strcmp(text, "Required Version does not match 2"), "failed version text does not match"); } try { KeySet config; config.append( Key("system/require_version", KEY_VALUE, "2", KEY_END) ); TypeChecker tc(config); succeed_if (true, "version should match"); } catch (const char *text) { succeed_if (false, "version should match"); } }
kdb::Key mountBackend (int iteration) { using namespace kdb; using namespace kdb::tools; Key mp = getMountpointForIteration<VARIANT> (iteration); std::string cf = "benchmark_" + plugin_variant_names[VARIANT] + "_" + std::to_string (iteration) + ".ecf"; unlink (cf.c_str ()); KDB kdb; KeySet mountConfig; kdb.get (mountConfig, "system/elektra/mountpoints"); MountBackendBuilder b; b.setMountpoint (mp, KeySet (0, KS_END)); b.addPlugin (PluginSpec ("resolver")); b.useConfigFile (cf); b.addPlugin (PluginSpec ("dump")); if (VARIANT != NO_CRYPTO) { KeySet pluginConfig; pluginConfig.append (Key ("user/encrypt/key", KEY_VALUE, GPG_TEST_KEY_ID, KEY_END)); pluginConfig.append (Key ("user/gpg/unit_test", KEY_VALUE, "1", KEY_END)); b.addPlugin (PluginSpec (plugin_variant_names[VARIANT], pluginConfig)); } b.validated (); b.serialize (mountConfig); kdb.set (mountConfig, "system/elektra/mountpoints"); kdb.close (); return mp; }
int CpCommand::execute (Cmdline const & cl) { if (cl.arguments.size () != 2) { throw invalid_argument ("wrong number of arguments, 2 needed"); } KeySet conf; Key sourceKey = cl.createKey (0); if (!sourceKey.isValid ()) { throw invalid_argument ("Source given is not a valid keyname"); } Key destKey = cl.createKey (1); if (!destKey.isValid ()) { throw invalid_argument ("Destination given is not a valid keyname"); } string newDirName = destKey.getName (); kdb.get (conf, sourceKey); kdb.get (conf, destKey); KeySet tmpConf = conf; KeySet oldConf; oldConf.append (tmpConf.cut (sourceKey)); KeySet newConf; oldConf.rewind (); std::string sourceName = sourceKey.getName (); if (cl.verbose) cout << "common name: " << sourceName << endl; if (cl.recursive) { // copy all keys with new name Key k; while ((k = oldConf.next ())) { Key rk = rename_key (k, sourceName, newDirName, cl.verbose); copySingleKey (cl, rk, tmpConf, newConf); } } else { // just copy one key Key k = oldConf.next (); Key rk = rename_key (k, sourceName, newDirName, cl.verbose); copySingleKey (cl, rk, tmpConf, newConf); } newConf.append (tmpConf); // these are unrelated keys newConf.append (oldConf); // these are the original keys newConf.rewind (); kdb.set (newConf, destKey); return 0; }
int FstabCommand::execute (Cmdline const & cl) { int argc = cl.arguments.size (); if (argc != 5 && argc != 6 && argc != 7) { throw invalid_argument ("number of arguments not correct, need 5, 6 or 7"); } KeySet conf; Key parentKey = cl.createKey (0); kdb.get (conf, parentKey); printWarnings (cerr, parentKey); Key k = conf.lookup (parentKey); if (!k) { k = cl.createKey (0); conf.append (k); } std::string keyname = k.getName (); string dumpfreq = "0"; if (argc >= 6) { dumpfreq = cl.arguments[5].c_str (); } string passno = "0"; if (argc >= 7) { passno = cl.arguments[6].c_str (); } kdb::KeySet config (20, *kdb::Key (keyname + "/ZZZNewFstabName", KEY_END), *kdb::Key (keyname + "/ZZZNewFstabName/device", KEY_VALUE, cl.arguments[1].c_str (), KEY_END), *kdb::Key (keyname + "/ZZZNewFstabName/mpoint", KEY_VALUE, cl.arguments[2].c_str (), KEY_END), *kdb::Key (keyname + "/ZZZNewFstabName/type", KEY_VALUE, cl.arguments[3].c_str (), KEY_END), *kdb::Key (keyname + "/ZZZNewFstabName/options", KEY_VALUE, cl.arguments[4].c_str (), KEY_END), *kdb::Key (keyname + "/ZZZNewFstabName/dumpfreq", KEY_VALUE, dumpfreq.c_str (), KEY_END), *kdb::Key (keyname + "/ZZZNewFstabName/passno", KEY_VALUE, passno.c_str (), KEY_END), KS_END); conf.append (config); if (cl.verbose) { cout << conf; } kdb.set (conf, parentKey); printWarnings (cerr, parentKey); return 0; }
/** * @brief Allows for updating of a database entry. * * Will renew the entry and all its subkeys (configuration). * * @param entry A custom Entry object holding current information. * @return true if the entry was updated, false if not * @throw kdbrest::exception::EntryNotFoundException in case the entry * to update does not exist. */ bool StorageEngine::updateEntry (model::Entry & entry) { using namespace kdb; // register exclusive access boost::unique_lock<boost::shared_mutex> lock (m_mutex_entryCache); bool found = false; std::vector<model::Entry> & entries = this->m_entryCache; unsigned int i = 0; while (i < entries.size ()) { if (entries[i].getName ().compare (entry.getName ()) == 0) { found = true; break; } i++; } if (!found) { throw exception::EntryNotFoundException (); } KDB kdb; KeySet ks; kdb.get (ks, entry.getName ()); Key k = ks.lookup (entry.getName ()); if (!k) { throw kdbrest::exception::EntryNotFoundException (); } ks.cut (entry); ks.append (entry); ks.append (entry.getSubkeys ()); if (kdb.set (ks, entry.getName ()) >= 1) { entries.erase (entries.begin () + i); entries.push_back (entry); return true; } else { return false; } }
TEST (test_contextual_policy, root) { using namespace kdb; KeySet ks; ks.append (Key ("user/available", KEY_VALUE, "12", KEY_END)); Context c; // clang-format off ContextualValue<int, GetPolicyIs<MyDynamicGetPolicy>> cv (ks, c, Key("/", KEY_CASCADING_NAME, KEY_META, "default", "88", KEY_META, "override/#0", "user/available", KEY_END)); // clang-format on EXPECT_EQ (cv, 12); EXPECT_EQ (cv, cv); cv = 40; EXPECT_EQ (cv, 40); c.activate<RootLayer> (); EXPECT_EQ (cv, 40); ContextualValue<int, GetPolicyIs<MyDynamicGetPolicy>> cv2 (cv); EXPECT_EQ (cv, cv2); }
int main () { using namespace kdb; std::vector<Key> vc; vc.push_back (Key ("user/key3/1", KEY_META, "order", "2", KEY_END)); vc.push_back (Key ("user/begin", KEY_META, "order", "1", KEY_END)); vc.push_back (Key ("user/key3/4", KEY_META, "order", "3", KEY_END)); vc.push_back (Key ("user/key3/dup", KEY_META, "order", "4", KEY_END)); vc.push_back (Key ("user/key3/dup", KEY_END)); vc.push_back (Key ("user/unordered", KEY_END)); vc.push_back (Key ("user/end", KEY_META, "order", "5", KEY_END)); std::sort (vc.begin (), vc.end (), keyOrder); KeySet ks (20, KS_END); std::cout << "Our Vector with special ordering:" << std::endl; for (auto k : vc) { std::cout << k.getName () << std::endl; ks.append (k); } // now we have a keyset (of course again with KeySet ordering and // duplicates removed. std::cout << "\nNow KeySet:" << std::endl; for (auto && ks_i : ks) { Key k (ks_i); std::cout << k.getName () << std::endl; } }
TEST_F (Simple, SetSystemGetAppend2) { using namespace kdb; KDB kdb; KeySet ks; Key parentKey (testRoot, KEY_END); ks.append (Key ("system" + testRoot + "key", KEY_VALUE, "value1", KEY_END)); kdb.get (ks, parentKey); ASSERT_EQ (ks.size (), 1) << "got keys from freshly mounted backends"; ks.rewind (); ks.next (); EXPECT_EQ (ks.current ().getName (), "system/tests/kdb/key") << "name of element in keyset wrong"; EXPECT_EQ (ks.current ().getString (), "value1") << "string of element in keyset wrong"; kdb.set (ks, parentKey); kdb.close (parentKey); KeySet ks2; ks2.append (Key ("system" + testRoot + "key2", KEY_VALUE, "value2", KEY_END)); kdb.open (parentKey); kdb.get (ks2, parentKey); ks2.rewind (); ks2.next (); ASSERT_EQ (ks2.size (), 1) << "wrong size"; EXPECT_EQ (ks2.current ().getName (), "system/tests/kdb/key") << "name of element in keyset wrong"; EXPECT_EQ (ks2.current ().getString (), "value1") << "string of element in keyset wrong"; }
void SpecMountpointReader::processKey (Key const & ck) { Key k (ck); k.rewindMeta (); Key m; while ((m = k.nextMeta ())) { std::string const & cn = "config/needs"; if (startsWith (m.getName (), cn)) { Key bKey = m.dup (); bKey.setName ("user" + bKey.getName ().substr (cn.length ())); backendConfig.append (bKey); } else if (m.getName () == "infos/plugins") { bb.addPlugins (parseArguments (m.getString ())); } else if (m.getName () == "infos/needs") { bb.needPlugin (m.getString ()); } else if (m.getName () == "infos/recommends") { bb.recommendPlugin (m.getString ()); } else if (isToBeIgnored (m.getName ())) { } else { bb.needMetadata (m.getName ()); } } }
TEST_F (Simple, TriggerError) { using namespace kdb; KDB kdb; KeySet ks; EXPECT_EQ (kdb.get (ks, testRoot), 0) << "nothing to do in get"; ks.append (Key ("system" + testRoot + "a", KEY_END)); ks.append (Key ("system" + testRoot + "k", KEY_META, "trigger/error", "10", KEY_END)); ks.append (Key ("system" + testRoot + "z", KEY_END)); struct stat buf; ASSERT_EQ (stat (mp->systemConfigFile.c_str (), &buf), -1) << "found wrong file"; EXPECT_THROW (kdb.set (ks, testRoot), kdb::KDBException) << "could not trigger error"; ASSERT_EQ (ks.size (), 3) << "key suddenly missing"; EXPECT_EQ (ks.current ().getName (), "system" + testRoot + "k") << "ks should point to error key"; ASSERT_EQ (stat (mp->systemConfigFile.c_str (), &buf), -1) << "created file even though error triggered"; }
TEST_F (Simple, GetSystem) { using namespace kdb; KDB kdb; KeySet ks; Key parentKey ("system" + testRoot, KEY_END); ks.append (Key (parentKey.getName () + "/key", KEY_END)); EXPECT_NE (kdb.get (ks, parentKey), -1); ASSERT_EQ (ks.size (), 1) << "no key stayed" << ks; ks.rewind (); ks.next (); EXPECT_EQ (ks.current ().getName (), "system/tests/kdb/key") << "name of element in keyset wrong"; EXPECT_EQ (ks.current ().getString (), "") << "string of element in keyset wrong"; ASSERT_NE (kdb.set (ks, parentKey), -1); ks.rewind (); ks.next (); EXPECT_EQ (ks.current ().getName (), "system/tests/kdb/key") << "name of element in keyset wrong"; EXPECT_EQ (ks.current ().getString (), "") << "string of element in keyset wrong"; kdb.close (parentKey); KeySet ks2; kdb.open (parentKey); kdb.get (ks2, parentKey); ks.rewind (); ks.next (); EXPECT_EQ (ks.current ().getName (), "system/tests/kdb/key") << "name of element in keyset wrong"; EXPECT_EQ (ks.current ().getString (), "") << "string of element in keyset wrong"; }
/** * @brief This function converts the given YAML file to keys and adds the * result to `keySet`. * * @param keySet The function adds the converted keys to this variable. * @param parent The function uses this parent key of `keySet` to emit error * information. * @param filename This parameter stores the path of the YAML file this * function converts. * * @retval -1 if there was an error converting the YAML file * @retval 0 if parsing was successful and the function did not change the * given keyset * @retval 1 if parsing was successful and the function did change `keySet` */ int addToKeySet (KeySet & keySet, Key & parent, string const & filename) { using std::runtime_error; using tao::TAO_PEGTL_NAMESPACE::analyze; using tao::TAO_PEGTL_NAMESPACE::file_input; using tao::TAO_PEGTL_NAMESPACE::normal; using tao::TAO_PEGTL_NAMESPACE::parse_error; using tao::TAO_PEGTL_NAMESPACE::parse_tree::parse; State state; #if DEBUG // Check grammar for problematic code if (analyze<yaml> () != 0) { throw runtime_error ("PEGTLs analyze function found problems while checking the top level grammar rule `yaml`!"); return -1; } #endif file_input<> input{ filename }; /* For detailed debugging information, please use the control class `tracer` instead of `normal`. */ auto root = parse<yaml, selector, action, normal> (input, state); Listener listener{ parent }; walk (listener, *root); auto keys = listener.getKeySet (); int status = (keys.size () <= 0) ? 0 : 1; keySet.append (keys); return status; }
void TestCommand::doBasicTest () { { KDB kdb; Key t = root.dup (); t.addBaseName ("basic"); t.setString ("BasicString"); KeySet basic; basic.append (t); KeySet test; kdb.get (test, root); kdb.set (basic, root); } { KDB kdb; Key t = root.dup (); t.addBaseName ("basic"); t.setString ("BasicString"); KeySet test; kdb.get (test, root); nrTest++; if (!test.lookup (t)) { nrError++; cerr << "Basic test failed" << endl; } } }
TEST_F (Simple, RemoveFile) { using namespace kdb; KDB kdb; KeySet ks; kdb.get (ks, testRoot); ks.append (Key ("system" + testRoot + "remove", KEY_END)); ASSERT_EQ (ks.size (), 1) << "could not append key\n" << ks; kdb.set (ks, testRoot); ASSERT_EQ (ks.size (), 1) << "key gone after kdb.set?\n" << ks; struct stat buf; ASSERT_EQ (stat (mp->systemConfigFile.c_str (), &buf), 0) << "found no file"; Key parentKey; kdb.close (parentKey); kdb.open (parentKey); kdb.get (ks, testRoot); ks.clear (); ASSERT_EQ (ks.size (), 0) << "keyset should be empty after clearing it\n" << ks; kdb.set (ks, testRoot); ASSERT_EQ (stat (mp->systemConfigFile.c_str (), &buf), -1) << "found wrong file"; }
void SetPlugins::serialise (Key & baseKey, KeySet & ret) { ret.append (*Key (baseKey.getName () + "/setplugins", KEY_COMMENT, "List of plugins to use", KEY_END)); for (int i = 0; i < NR_OF_PLUGINS; ++i) { if (plugins[i] == nullptr) continue; bool fr = plugins[i]->firstRef; std::ostringstream pluginNumber; pluginNumber << i; std::string name = baseKey.getName () + "/setplugins/#" + pluginNumber.str () + plugins[i]->refname (); ret.append (*Key (name, KEY_COMMENT, "A plugin", KEY_END)); if (fr) serializeConfig (name, plugins[i]->getConfig (), ret); } }
void SpecReader::readSpecification (KeySet const & cks) { KeySet ks; Key mp; // only accept keys in 'spec' namespace for (Key k : cks) { if (k.isSpec ()) { ks.append (k); } } ks.rewind (); // we need old fashioned loop, because it can handle ks.cut during iteration for (Key k = ks.next (); k; k = ks.next ()) { // search for mountpoint Key m = k.getMeta<const Key> ("mountpoint"); if (m) { SpecMountpointReader smr (backends, bbi); backends[k] = smr.readMountpointSpecification (ks.cut (k)); } } }
TEST_F (Simple, GetAppendMeta) { using namespace kdb; KDB kdb; KeySet ks; ks.append (Key ("meta/key", KEY_META_NAME, KEY_END)); Key parentKey (testRoot, KEY_END); kdb.get (ks, parentKey); ASSERT_EQ (ks.size (), 1) << "no key stayed"; ks.rewind (); ks.next (); EXPECT_EQ (ks.current ().getName (), "meta/key") << "name of element in keyset wrong"; EXPECT_EQ (ks.current ().getString (), "") << "string of element in keyset wrong"; kdb.set (ks, parentKey); ks.rewind (); ks.next (); EXPECT_EQ (ks.current ().getName (), "meta/key") << "name of element in keyset wrong"; EXPECT_EQ (ks.current ().getString (), "") << "string of element in keyset wrong"; kdb.close (parentKey); KeySet ks2; kdb.open (parentKey); kdb.get (ks2, parentKey); ASSERT_EQ (ks2.size (), 0) << "got keys from freshly mounted backends"; }
void TestCommand::doStringTest () { vector<string> teststrings; teststrings.push_back (""); teststrings.push_back ("value"); teststrings.push_back ("value with spaces"); teststrings.push_back (" a very long value with many spaces and basically very very long, but only text ... "); for (int i = 1; i < 256; ++i) teststrings.back () += " very very long, but only text ... "; for (auto & teststring : teststrings) { { KDB kdb; Key t = root.dup (); t.addBaseName ("string"); t.setString (teststring); KeySet basic; basic.append (t); KeySet test; kdb.get (test, root); kdb.set (basic, root); } { KDB kdb; KeySet test; kdb.get (test, root); Key t = root.dup (); t.addBaseName ("string"); Key res = test.lookup (t); nrTest++; if (!res) { nrError++; cerr << "String test failed (key not found)" << t.getName () << endl; continue; } nrTest++; if (res.getString () != teststring) { nrError++; cerr << "String test failed (value is not equal)" << endl; cerr << "We got: \"" << res.getString () << "\"" << endl; cerr << "We wanted: \"" << teststring << "\"" << endl; } } } }
TEST (MergeResult, CountsEqualKeysCorrectly) { Key mergedKey1 = Key ("user/test/config/key1", KEY_END); Key mergedKey2 = Key ("user/test/config/key2", KEY_END); Key mergedKey3 = Key ("user/test/config/key3", KEY_END); Key conflictKey1 = Key ("user/test/config/key4", KEY_END); KeySet conflicts; conflicts.append (conflictKey1); KeySet merged; merged.append (mergedKey1); merged.append (mergedKey2); MergeResult result (conflicts, merged); EXPECT_EQ (2, result.getNumberOfEqualKeys ()) << "Initially merged keys not counted"; result.resolveConflict (conflictKey1); result.addMergeKey (conflictKey1); EXPECT_EQ (2, result.getNumberOfEqualKeys ()) << "Resolved key is counted as equal key"; result.addMergeKey (mergedKey3); EXPECT_EQ (3, result.getNumberOfEqualKeys ()) << "Merged key is not counted as equal key"; }
void PluginVariantDatabase::addKeysBelowKeyToConf (Key const & below, KeySet const & conf, Key const & newbase, KeySet & targetconf) const { KeySet confCp (conf); KeySet ksVariantSysConf = confCp.cut (below); for (auto kVariantCurrent : ksVariantSysConf) { if (!kVariantCurrent.isBelow (below)) continue; targetconf.append (helper::rebaseKey (kVariantCurrent, below, newbase)); } }
TEST (MergeResult, IsConflictWorks) { Key conflictKey = Key ("user/test/config/key1", KEY_END); KeySet conflicts; conflicts.append (conflictKey); KeySet merged; MergeResult result (conflicts, merged); EXPECT_TRUE (result.isConflict (conflictKey)); EXPECT_FALSE (result.isConflict (Key ("user/test/config/key2", KEY_END))); }
int MetaSetCommand::execute (Cmdline const & cl) { if (cl.arguments.size () < 2 || cl.arguments.size () > 3) { throw invalid_argument ("Need 2 or 3 arguments"); } string metaname = cl.arguments[1]; Key parentKey = cl.createKey (0); string keyname = parentKey.getName (); if (keyname[0] == '/') { // fix name for lookup keyname = "spec" + keyname; if (!cl.quiet) std::cout << "Using keyname " << keyname << std::endl; // fix k for kdb.set later parentKey.setName (keyname); } KeySet conf; kdb.get (conf, parentKey); Key k = conf.lookup (parentKey); if (!k) { k = Key (keyname, KEY_END); // k.setBinary(0, 0); // conceptually maybe better, but would have confusing "binary" metadata conf.append (k); if (cl.verbose) cout << "Creating key " << keyname << endl; } if (!k.isValid ()) { cerr << "Could not create key " << keyname << endl; return 1; } if (cl.arguments.size () == 2) { if (!cl.quiet) cout << "Only two arguments, thus deleting metaname " << metaname << endl; k.delMeta (metaname); } else { std::string metavalue = cl.arguments[2]; if (metaname == "atime" || metaname == "mtime" || metaname == "ctime") { stringstream str (metavalue); time_t t; str >> t; if (!str.good ()) throw "conversion failure"; k.setMeta<time_t> (metaname, t); } else {
TEST_F (Simple, InvalidKeysInSet) { using namespace kdb; KDB kdb; KeySet ks; Key parent (testRoot, KEY_END); kdb.get (ks, parent); ASSERT_EQ (ks.size (), 0) << "got keys from freshly mounted backend" << ks; ks.append (Key (testRoot + "wrong_cascading_key", KEY_END)); ks.append (Key ("meta" + testRoot + "wrong_meta_key", KEY_META_NAME, KEY_END)); ASSERT_EQ (ks.size (), 2) << "keys not inserted:\n" << ks; kdb.set (ks, parent); printError (std::cout, parent); printWarnings (std::cout, parent); ASSERT_EQ (ks.size (), 2) << "got wrong keys:\n" << ks; struct stat buf; ASSERT_EQ (stat (mp->systemConfigFile.c_str (), &buf), -1) << "did find config file"; }
TEST (MergeResult, ResolveConflictRemovesKeyFromConflicts) { Key conflictKey = Key ("user/test/config/key1", KEY_VALUE, "testvalue", KEY_END); KeySet conflicts; conflicts.append (conflictKey); KeySet merged; MergeResult result (conflicts, merged); result.resolveConflict (conflictKey); EXPECT_EQ (0, result.getConflictSet ().size ()); }
/** * Add a plugin that can be loaded, meets all * constraints. * * @note that this does not mean that the backend * validates after it is added. It only means that * the situation is not getting worse. * * @throw PluginCheckException or its subclasses if it was not possible * to load the plugin * * For validation @see validated(). */ void Backend::addPlugin (PluginSpec const & plugin) { KeySet fullPluginConfig = plugin.getConfig (); fullPluginConfig.append (plugin.getConfig ()); // add previous configs tryPlugin (plugin); errorplugins.addPlugin (*plugins.back ()); getplugins.addPlugin (*plugins.back ()); setplugins.addPlugin (*plugins.back ()); KeySet toAdd = plugins.back ()->getNeededConfig (); config.append (toAdd); }
TEST (MergeResult, HasConflictsWorks) { Key conflictKey = Key ("user/test/config/key1", KEY_END); KeySet conflicts; conflicts.append (conflictKey); KeySet merged; MergeResult result (conflicts, merged); EXPECT_TRUE (result.hasConflicts ()); conflicts = KeySet (); result = MergeResult (merged, conflicts); EXPECT_FALSE (result.hasConflicts ()); }
/** * @brief Can be used to create an entry in the database. * * Will add the entry and all subkeys to the database (configuration). * * @param entry A custom Entry object holding information to store. * @return true if the entry was stored, false if something went wrong * @throws kdbrest::exception::EntryAlreadyExistsException in case an * entry with the given name does already exist in the key database. */ bool StorageEngine::createEntry (model::Entry & entry) { using namespace kdb; // register exclusive access boost::unique_lock<boost::shared_mutex> lock (m_mutex_entryCache); std::vector<model::Entry> & entries = this->m_entryCache; for (auto & elem : entries) { if (elem.getName ().compare (entry.getName ()) == 0) { throw exception::EntryAlreadyExistsException (); } } KDB kdb; KeySet ks; kdb.get (ks, entry.getName ()); Key k = ks.lookup (entry.getName ()); if (k) { throw kdbrest::exception::EntryAlreadyExistsException (); } ks.append (entry); ks.append (entry.getSubkeys ()); if (kdb.set (ks, entry.getName ()) >= 1) { entries.push_back (entry); return true; } else { return false; } }
/** * @brief Can be used to create an user entry in the database. * * Will add the user and all subkeys to the database (additional information). * * @param user A custom User object holding information to store. * @return true if the user was stored, false if something went wrong * @throws kdbrest::exception::UserAlreadyExistsException in case an * user with the given name does already exist in the key database. */ bool StorageEngine::createUser (model::User & user) { using namespace kdb; // register exclusive access boost::unique_lock<boost::shared_mutex> lock (m_mutex_userCache); std::vector<model::User> & users = this->m_userCache; for (auto & elem : users) { if (elem.getName ().compare (user.getName ()) == 0) { throw exception::UserAlreadyExistsException (); } } KDB kdb; KeySet ks; kdb.get (ks, user.getName ()); Key k = ks.lookup (user.getName ()); if (k) { throw exception::UserAlreadyExistsException (); } ks.append (user); ks.append (user.getSubkeys ()); if (kdb.set (ks, user.getName ()) >= 1) { users.push_back (user); return true; } else { return false; } }
TEST (MergeResult, CountsResolvedKeysCorrectly) { Key conflictKey1 = Key ("user/test/config/key1", KEY_END); Key conflictKey2 = Key ("user/test/config/key2", KEY_END); KeySet conflicts; conflicts.append (conflictKey1); conflicts.append (conflictKey2); KeySet merged; MergeResult result (conflicts, merged); EXPECT_EQ (0, result.getNumberOfResolvedKeys ()); result.resolveConflict (conflictKey1); result.resolveConflict (conflictKey2); EXPECT_EQ (2, result.getNumberOfResolvedKeys ()); }
int main() { using namespace kdb; KDB kdb; KeySet ks; Context c; // some predefined values (for convenience): ks.append(Key("user/kate/quit", KEY_VALUE, "Ctrl+k", KEY_END)); KeySet ks2; kdb.get(ks2, "/myapp"); // overwrite them if something is available in config files: ks.append(ks2); Parameters par(ks,c); std::cout << par.myapp.shortcut.quitMyapp << std::endl; return 0; }