D-Bus API: allow reading template for non-existent context (MB #10448)

A client which wants to create a new config in a non-default context should
always use
   config = GetConfig("<template>@context", true)
   <make changes>
   SetConfig(config)
to ensure that shared properties in that context are preserved.

A client shouldn't have to check whether that context exists. If it doesn't,
the server should simply ignore the context and use the default values from the
template.

This patch adds a test for this, based on the "type" property. The expectation
in the test that the "type" is preserved literally is wrong. "type" currently
must not be preserved, because different templates may have to set
different data formats (MB #10443).
This commit is contained in:
Patrick Ohly 2010-03-30 17:39:36 +02:00
parent 8a12b94684
commit a3f4a06e95
2 changed files with 39 additions and 5 deletions

View File

@ -233,8 +233,14 @@ private:
*/
virtual bool setFilters(SyncConfig &config) { return false; }
/** utility method which constructs a SyncConfig which references a local configuration (never a template) */
boost::shared_ptr<DBusUserInterface> getLocalConfig(const std::string &configName);
/**
* utility method which constructs a SyncConfig which references a local configuration (never a template)
*
* In general, the config must exist, except in two cases:
* - configName = @default (considered always available)
* - mustExist = false (used when reading a templates for a context which might not exist yet)
*/
boost::shared_ptr<DBusUserInterface> getLocalConfig(const std::string &configName, bool mustExist = true);
};
/**
@ -2365,7 +2371,7 @@ void ReadOperations::getConfigs(bool getTemplates, std::vector<std::string> &con
}
}
boost::shared_ptr<DBusUserInterface> ReadOperations::getLocalConfig(const string &configName)
boost::shared_ptr<DBusUserInterface> ReadOperations::getLocalConfig(const string &configName, bool mustExist)
{
string peer, context;
SyncConfig::splitConfigString(SyncConfig::normalizeConfigString(configName),
@ -2378,7 +2384,8 @@ boost::shared_ptr<DBusUserInterface> ReadOperations::getLocalConfig(const string
// the default configuration can always be opened for reading,
// everything else must exist
if ((context != "default" || peer != "") &&
!syncConfig->exists()) {
mustExist &&
!syncConfig->exists()) {
SE_THROW_EXCEPTION(NoSuchConfig, "No configuration '" + configName + "' found");
}
}
@ -2434,7 +2441,7 @@ void ReadOperations::getConfig(bool getTemplate,
// use the shared properties from the right context as filter
// so that the returned template preserves existing properties
boost::shared_ptr<DBusUserInterface> shared = getLocalConfig(string("@") + context);
boost::shared_ptr<DBusUserInterface> shared = getLocalConfig(string("@") + context, false);
ConfigProps props;
shared->getProperties()->readProperties(props);

View File

@ -2101,6 +2101,33 @@ class TestMultipleConfigs(unittest.TestCase, DBusUtil):
config = self.server.GetConfig("@default", False, utf8_strings=True)
self.failUnlessEqual(config["source/addressbook"]["type"], "file:text/x-vcard:2.1")
def testSharedTypeOther(self):
"""'type' must not be overwritten when set in the context"""
# writing for peer modifies "type" in "foo" and context "@other"
self.setUpSession("Foo@other")
config = self.server.GetConfig("ScheduleWorld@other", True, utf8_strings=True)
config["source/addressbook"]["type"] = "file:text/vcard:3.0"
self.session.SetConfig(False, False,
config,
utf8_strings=True)
config = self.server.GetConfig("Foo", False, utf8_strings=True)
self.failUnlessEqual(config["source/addressbook"]["type"], "file:text/vcard:3.0")
config = self.server.GetConfig("@other", False, utf8_strings=True)
self.failUnlessEqual(config["source/addressbook"]["type"], "file:text/vcard:3.0")
self.session.Detach()
# adding second client must preserve type
self.setUpSession("bar@other")
config = self.server.GetConfig("Funambol@other", True, utf8_strings=True)
self.failUnlessEqual(config["source/addressbook"]["type"], "file:text/vcard:3.0")
self.session.SetConfig(False, False,
config,
utf8_strings=True)
config = self.server.GetConfig("bar", False, utf8_strings=True)
self.failUnlessEqual(config["source/addressbook"]["type"], "file:text/vcard:3.0")
config = self.server.GetConfig("@other", False, utf8_strings=True)
self.failUnlessEqual(config["source/addressbook"]["type"], "file:text/vcard:3.0")
def testOtherContext(self):
"""write into independent context"""
self.setupConfigs()