Introduce synchronize merge method

* Create history-based merging that keeps older data in history instead of discarding or deleting it
* Extract merge logic into the Merger class
* Allows special merge behavior
* Improve handling of deletion and changes on groups
* Enable basic change tracking while merging
* Prevent unintended timestamp changes while merging
* Handle differences in timestamp precision
* Introduce comparison operators to allow for more sophisticated comparisons (ignore special properties, ...)
* Introduce Clock class to handle datetime across the app

Merge Strategies:
* Default (use inherited/fallback method)
* Duplicate (duplicate conflicting nodes, apply all deletions)
* KeepLocal (use local values, but apply all deletions)
* KeepRemote (use remote values, but apply all deletions)
* KeepNewer (merge history only)
* Synchronize (merge history, newest value stays on top, apply all deletions)
This commit is contained in:
Jonathan White 2018-09-30 08:45:06 -04:00 committed by Jonathan White
parent b40e5686dc
commit c1e9f45df9
43 changed files with 2777 additions and 585 deletions

View file

@ -16,10 +16,12 @@
*/
#include "TestModified.h"
#include "stub/TestClock.h"
#include <QSignalSpy>
#include <QTest>
#include "core/Clock.h"
#include "core/Database.h"
#include "core/Group.h"
#include "core/Metadata.h"
@ -27,11 +29,29 @@
QTEST_GUILESS_MAIN(TestModified)
namespace
{
TestClock* m_clock = nullptr;
}
void TestModified::initTestCase()
{
QVERIFY(Crypto::init());
}
void TestModified::init()
{
Q_ASSERT(m_clock == nullptr);
m_clock = new TestClock(2010, 5, 5, 10, 30, 10);
TestClock::setup(m_clock);
}
void TestModified::cleanup()
{
TestClock::teardown();
m_clock = nullptr;
}
void TestModified::testSignals()
{
int spyCount = 0;
@ -230,7 +250,7 @@ void TestModified::testEntrySets()
entry->setExpires(entry->timeInfo().expires());
QCOMPARE(spyModified.count(), spyCount);
entry->setExpiryTime(QDateTime::currentDateTimeUtc().addYears(1));
entry->setExpiryTime(Clock::currentDateTimeUtc().addYears(1));
QCOMPARE(spyModified.count(), ++spyCount);
entry->setExpiryTime(entry->timeInfo().expiryTime());
QCOMPARE(spyModified.count(), spyCount);
@ -300,7 +320,7 @@ void TestModified::testHistoryItems()
QCOMPARE(entry->historyItems().size(), historyItemsSize);
QDateTime modified = entry->timeInfo().lastModificationTime();
QTest::qSleep(10);
m_clock->advanceSecond(10);
entry->beginUpdate();
entry->setTitle("b");
entry->endUpdate();