testing: more workarounds for Google CalDAV + unique IDs
Google became even more strict about checking REV. Tests which reused a UID after deleting the original item started to fail sometime since middle of December 2012. To fix this, tests must differentiate reuse of an item by adding a suffix ("-A", "-B", etc.). If CLIENT_TEST_UNIQUE_UID has a value >= 2, that suffix will be used when mangling the input item. Otherwise the suffix is ignored and nothing changes. For testing Google, CLIENT_TEST_UNIQUE_UID=2 is used.
This commit is contained in:
parent
7214834e0b
commit
bfe1b062cb
|
@ -276,8 +276,11 @@ struct ClientTestConfig {
|
|||
*
|
||||
* @param update modify item content so that it can be
|
||||
* used as an update of the old data
|
||||
* @param uniqueUIDSuffix beyond not reusing UIDs between tests, also embed this suffix
|
||||
* in test items inside the running test to avoid reuse
|
||||
* if necessary (Google CalDAV + UID/SEQUENCE => 409 error)
|
||||
*/
|
||||
boost::function<std::string (const std::string &, bool)> m_mangleItem;
|
||||
boost::function<std::string (const std::string &data, bool update, const std::string &uniqueUIDSuffix)> m_mangleItem;
|
||||
|
||||
/**
|
||||
* A very simple item that is inserted during basic tests. Ideally
|
||||
|
|
|
@ -392,7 +392,7 @@ static std::string importItem(TestingSyncSource *source, const ClientTestConfig
|
|||
CT_ASSERT(source);
|
||||
if (data.size()) {
|
||||
SyncSourceRaw::InsertItemResult res;
|
||||
SOURCE_ASSERT_NO_FAILURE(source, res = source->insertItemRaw("", config.m_mangleItem(data, false)));
|
||||
SOURCE_ASSERT_NO_FAILURE(source, res = source->insertItemRaw("", config.m_mangleItem(data, false, "")));
|
||||
CT_ASSERT(!res.m_luid.empty());
|
||||
return res.m_luid;
|
||||
} else {
|
||||
|
@ -547,7 +547,7 @@ void LocalTests::addTests() {
|
|||
}
|
||||
}
|
||||
|
||||
std::string LocalTests::insert(CreateSource createSource, const std::string &data, bool relaxed, std::string *inserted) {
|
||||
std::string LocalTests::insert(CreateSource createSource, const std::string &data, bool relaxed, std::string *inserted, const std::string &uniqueUIDSuffix) {
|
||||
restoreStorage(config, client);
|
||||
|
||||
// create source
|
||||
|
@ -558,7 +558,7 @@ std::string LocalTests::insert(CreateSource createSource, const std::string &dat
|
|||
int numItems = 0;
|
||||
CT_ASSERT_NO_THROW(numItems = countItems(source.get()));
|
||||
SyncSourceRaw::InsertItemResult res;
|
||||
std::string mangled = config.m_mangleItem(data, false);
|
||||
std::string mangled = config.m_mangleItem(data, false, uniqueUIDSuffix);
|
||||
if (inserted) {
|
||||
*inserted = mangled;
|
||||
}
|
||||
|
@ -607,7 +607,7 @@ static std::string updateItem(CreateSource createSource, const ClientTestConfig
|
|||
// insert item
|
||||
SyncSourceRaw::InsertItemResult res;
|
||||
std::string mangled;
|
||||
CT_ASSERT_NO_THROW(mangled = config.m_mangleItem(data, true));
|
||||
CT_ASSERT_NO_THROW(mangled = config.m_mangleItem(data, true, ""));
|
||||
if (updated) {
|
||||
*updated = mangled;
|
||||
}
|
||||
|
@ -630,7 +630,7 @@ static void removeItem(CreateSource createSource, const std::string &luid)
|
|||
SOURCE_ASSERT_NO_FAILURE(source.get(), source->deleteItem(luid));
|
||||
}
|
||||
|
||||
void LocalTests::update(CreateSource createSource, const std::string &data, bool check) {
|
||||
void LocalTests::update(CreateSource createSource, const std::string &data, bool check, const std::string &uniqueUIDSuffix) {
|
||||
CT_ASSERT(createSource.createSource);
|
||||
|
||||
restoreStorage(config, client);
|
||||
|
@ -645,7 +645,8 @@ void LocalTests::update(CreateSource createSource, const std::string &data, bool
|
|||
CT_ASSERT(it != source->getAllItems().end());
|
||||
string luid = *it;
|
||||
SyncSourceRaw::InsertItemResult res;
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), res = source->insertItemRaw(luid, config.m_mangleItem(data, true)));
|
||||
std::string mangled = config.m_mangleItem(data, true, uniqueUIDSuffix);
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), res = source->insertItemRaw(luid, mangled));
|
||||
CT_ASSERT_NO_THROW(source.reset());
|
||||
CT_ASSERT_EQUAL(luid, res.m_luid);
|
||||
CT_ASSERT_EQUAL(ITEM_OKAY, res.m_state);
|
||||
|
@ -677,7 +678,7 @@ void LocalTests::update(CreateSource createSource, const std::string &data, cons
|
|||
SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSource()));
|
||||
|
||||
// update it
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), source->insertItemRaw(luid, config.m_mangleItem(data, true)));
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), source->insertItemRaw(luid, config.m_mangleItem(data, true, "")));
|
||||
|
||||
backupStorage(config, client);
|
||||
}
|
||||
|
@ -790,7 +791,7 @@ void LocalTests::compareDatabasesRef(TestingSyncSource ©,
|
|||
|
||||
std::string LocalTests::createItem(int item, const std::string &revision, int size)
|
||||
{
|
||||
std::string data = config.m_mangleItem(config.m_templateItem, false);
|
||||
std::string data = config.m_mangleItem(config.m_templateItem, false, "");
|
||||
std::stringstream prefix;
|
||||
|
||||
// string to be inserted at start of unique properties;
|
||||
|
@ -1108,7 +1109,7 @@ void LocalTests::testInsertTwice() {
|
|||
SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSourceA()));
|
||||
|
||||
// mangle data once
|
||||
std::string data = config.m_mangleItem(config.m_insertItem, false);
|
||||
std::string data = config.m_mangleItem(config.m_insertItem, false, "");
|
||||
|
||||
// insert new item
|
||||
SyncSourceRaw::InsertItemResult first;
|
||||
|
@ -1201,11 +1202,12 @@ void LocalTests::doChanges(bool restart) {
|
|||
CT_ASSERT_EQUAL(luid, *it);
|
||||
CT_ASSERT_NO_THROW(restart ? source.stopAccess() : source.reset());
|
||||
|
||||
// now make changes via source B directly: these changes are not to be
|
||||
// reported back
|
||||
// Now make changes via source B directly: these changes are not to be
|
||||
// reported back. Google CalDAV is very strict about UID/SEQUENCE,
|
||||
// work around that by not reusing a UID inside this test.
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), restart ? source.startAccess() : source.reset(createSourceB()));
|
||||
// add
|
||||
std::string mangled = config.m_mangleItem(config.m_insertItem, false);
|
||||
std::string mangled = config.m_mangleItem(config.m_insertItem, false, "-B");
|
||||
SyncSourceRaw::InsertItemResult res;
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), res = source->insertItemRaw("", mangled));
|
||||
CT_ASSERT(!res.m_luid.empty());
|
||||
|
@ -1216,7 +1218,7 @@ void LocalTests::doChanges(bool restart) {
|
|||
SOURCE_ASSERT_EQUAL(source.get(), 0, countNewItems(source.get()));
|
||||
SOURCE_ASSERT_EQUAL(source.get(), 0, countUpdatedItems(source.get()));
|
||||
SOURCE_ASSERT_EQUAL(source.get(), 0, countDeletedItems(source.get()));
|
||||
mangled = config.m_mangleItem(config.m_updateItem, false);
|
||||
mangled = config.m_mangleItem(config.m_updateItem, false, "-B");
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), res = source->insertItemRaw(res.m_luid, mangled));
|
||||
CT_ASSERT_NO_THROW(restart ? source.stopAccess() : source.reset());
|
||||
// delete
|
||||
|
@ -1235,7 +1237,7 @@ void LocalTests::doChanges(bool restart) {
|
|||
CT_ASSERT_NO_THROW(restart ? source.stopAccess() : source.reset());
|
||||
|
||||
CLIENT_TEST_LOG("insert another item via source A");
|
||||
CT_ASSERT_NO_THROW(doInsert());
|
||||
CT_ASSERT_NO_THROW(insert(createSourceA, config.m_insertItem, false, NULL, "-C"));
|
||||
CLIENT_TEST_LOG("check for new item via source B");
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), restart ? source.startAccess() : source.reset(createSourceB()));
|
||||
SOURCE_ASSERT_EQUAL(source.get(), 1, countItems(source.get()));
|
||||
|
@ -1254,7 +1256,7 @@ void LocalTests::doChanges(bool restart) {
|
|||
CT_ASSERT_NO_THROW(restart ? source.stopAccess() : source.reset());
|
||||
|
||||
CLIENT_TEST_LOG("update item via source A");
|
||||
CT_ASSERT_NO_THROW(update(createSourceA, config.m_updateItem));
|
||||
CT_ASSERT_NO_THROW(update(createSourceA, config.m_updateItem, "-C"));
|
||||
CLIENT_TEST_LOG("check for updated item via source B");
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), restart ? source.startAccess() : source.reset(createSourceB()));
|
||||
SOURCE_ASSERT_EQUAL(source.get(), 1, countItems(source.get()));
|
||||
|
@ -1281,8 +1283,10 @@ void LocalTests::doChanges(bool restart) {
|
|||
SOURCE_ASSERT_NO_FAILURE(source.get(), restart ? source.startAccess() : source.reset(createSourceB()));
|
||||
CT_ASSERT_NO_THROW(restart ? source.stopAccess() : source.reset());
|
||||
CLIENT_TEST_LOG("create and update an item in source A");
|
||||
CT_ASSERT_NO_THROW(doInsert());
|
||||
CT_ASSERT_NO_THROW(update(createSourceA, config.m_updateItem));
|
||||
// Must use a UID different than the one used before despite that data being gone,
|
||||
// to keep Google CalDAV server happy.
|
||||
CT_ASSERT_NO_THROW(insert(createSourceA, config.m_insertItem, false, NULL, "-D"));
|
||||
CT_ASSERT_NO_THROW(update(createSourceA, config.m_updateItem, "-D"));
|
||||
CLIENT_TEST_LOG("should only be listed as new or updated in source B, but not both");
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), restart ? source.startAccess() : source.reset(createSourceB()));
|
||||
SOURCE_ASSERT_EQUAL(source.get(), 1, countItems(source.get()));
|
||||
|
@ -1295,9 +1299,9 @@ void LocalTests::doChanges(bool restart) {
|
|||
SOURCE_ASSERT_NO_FAILURE(source.get(), restart ? source.startAccess() : source.reset(createSourceB()));
|
||||
CT_ASSERT_NO_THROW(restart ? source.stopAccess() : source.reset());
|
||||
CLIENT_TEST_LOG("create, delete and recreate an item in source A");
|
||||
CT_ASSERT_NO_THROW(doInsert());
|
||||
CT_ASSERT_NO_THROW(insert(createSourceA, config.m_insertItem, false, NULL, "-E"));
|
||||
CT_ASSERT_NO_THROW(deleteAll(createSourceA));
|
||||
CT_ASSERT_NO_THROW(doInsert());
|
||||
CT_ASSERT_NO_THROW(insert(createSourceA, config.m_insertItem, false, NULL, "-F"));
|
||||
CLIENT_TEST_LOG("should only be listed as new or updated in source B, even if\n "
|
||||
"(as for calendar with UID) the same LUID gets reused");
|
||||
SOURCE_ASSERT_NO_FAILURE(source.get(), restart ? source.startAccess() : source.reset(createSourceB()));
|
||||
|
@ -6375,7 +6379,7 @@ void ClientTest::postSync(int res, const std::string &logname)
|
|||
#endif
|
||||
}
|
||||
|
||||
static string mangleGeneric(const std::string &data, bool update)
|
||||
static string mangleGeneric(const std::string &data, bool update, const std::string &uniqueUIDSuffix)
|
||||
{
|
||||
std::string item = data;
|
||||
if (update) {
|
||||
|
@ -6384,7 +6388,7 @@ static string mangleGeneric(const std::string &data, bool update)
|
|||
return item;
|
||||
}
|
||||
|
||||
static string mangleICalendar20(const std::string &data, bool update)
|
||||
static string mangleICalendar20(const std::string &data, bool update, const std::string &uniqueUIDSuffix)
|
||||
{
|
||||
std::string item = data;
|
||||
std::string type;
|
||||
|
@ -6420,6 +6424,13 @@ static string mangleICalendar20(const std::string &data, bool update)
|
|||
}
|
||||
std::string unique = StringPrintf("UID:UNIQUE-UID-%llu-", (long long unsigned)start);
|
||||
boost::replace_all(item, "UID:", unique);
|
||||
if (atoi(getenv("CLIENT_TEST_UNIQUE_UID")) > 1) {
|
||||
// Also avoid reusing the same UID inside the same test.
|
||||
// Required by Google CalDAV in calendar testChanges, because
|
||||
// they keep even deleted items around and check the SEQUENCE
|
||||
// number against their old data.
|
||||
boost::replace_all(item, "UNIQUE-UID", "UNIQUE-UID" + uniqueUIDSuffix);
|
||||
}
|
||||
} else if (getenv("CLIENT_TEST_LONG_UID")) {
|
||||
boost::replace_all(item, "UID:", "UID:this-is-a-ridiculously-long-uid-");
|
||||
}
|
||||
|
|
|
@ -520,16 +520,18 @@ public:
|
|||
*
|
||||
* @param relaxed if true, then disable some of the additional checks after adding the item
|
||||
* @retval inserted actual data that was inserted, optional
|
||||
* @param uniqueUIDSuffix gets added to UID of the inserted item if unique UIDs are necessary
|
||||
* @return the LUID of the inserted item
|
||||
*/
|
||||
virtual std::string insert(CreateSource createSource, const std::string &data, bool relaxed = false, std::string *inserted = NULL);
|
||||
virtual std::string insert(CreateSource createSource, const std::string &data, bool relaxed = false, std::string *inserted = NULL, const std::string &uniqueUIDSuffix = "");
|
||||
|
||||
/**
|
||||
* assumes that exactly one element is currently inserted and updates it with the given item
|
||||
*
|
||||
* @param check if true, then reopen the source and verify that the reported items are as expected
|
||||
* @param uniqueUIDSuffix same UID suffix as when creating the item
|
||||
*/
|
||||
virtual void update(CreateSource createSource, const std::string &data, bool check = true);
|
||||
virtual void update(CreateSource createSource, const std::string &data, bool check = true, const std::string &uniqueUIDSuffix = "");
|
||||
|
||||
/**
|
||||
* updates one item identified by its LUID with the given item
|
||||
|
|
|
@ -1107,7 +1107,7 @@ test = SyncEvolutionTest("googlecalendar", compile,
|
|||
"CLIENT_TEST_WEBDAV='google caldav testcases=testcases/google_event.ics' "
|
||||
"CLIENT_TEST_NUM_ITEMS=10 " # don't stress server
|
||||
"CLIENT_TEST_SIMPLE_UID=1 " # server gets confused by UID with special characters
|
||||
"CLIENT_TEST_UNIQUE_UID=1 " # server keeps backups and restores old data unless UID is unieque
|
||||
"CLIENT_TEST_UNIQUE_UID=2 " # server keeps backups and complains with 409 about not increasing SEQUENCE number even after deleting old data
|
||||
"CLIENT_TEST_MODE=server " # for Client::Sync
|
||||
"CLIENT_TEST_FAILURES="
|
||||
# http://code.google.com/p/google-caldav-issues/issues/detail?id=61 "cannot remove detached recurrence"
|
||||
|
|
Loading…
Reference in New Issue