sw/qa/uitest/writer_tests/trackedChanges.py | 4 ++-- sw/source/core/doc/docredln.cxx | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-)
New commits: commit e8580b8ef2765d5bbaafadd46d395bc4be9345b2 Author: Stephan Bergmann <sberg...@redhat.com> AuthorDate: Fri Oct 21 20:57:14 2022 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Tue Oct 25 11:07:36 2022 +0200 Improve SwRedlineData::CanCombine date comparison f240f073d228e62afd3f60563c23626efad0df7f "Related: tdf#102308 sw: ignore seconds when combining redlines" had just naively cut off the seconds for comparison, but which apparently gave unexpected results when the two dates are sufficiently close but lie on different sides of a minute tick: Autocorrection-related unit tests like CppunitTest_sw_uiwriter6 CPPUNIT_TEST_NAME=testRedlineAutoCorrect2::TestBody sporadically failed to execute some autocorrection, as in > uiwriter6.cxx:1436:Assertion > Test name: testRedlineAutoCorrect2::TestBody > equality assertion failed > - Expected: Lorem,... Lorem,… > - Actual : Lorem,... Lorem,... What happened there in testRedlineAutoCorrect2 (sw/qa/extras/uiwriter/uiwriter6.cxx) is that each emulateTyping consecutive simulated character input should extend the current redline range, by hitting the > // Merge if applicable? > if( (( SwComparePosition::Behind == eCmpPos && > IsPrevPos( *pREnd, *pStt ) ) || > ( SwComparePosition::CollideStart == eCmpPos ) || > ( SwComparePosition::OverlapBehind == eCmpPos ) ) && > pRedl->CanCombine( *pNewRedl ) && > ( n+1 >= maRedlineTable.size() || > ( *maRedlineTable[ n+1 ]->Start() >= *pEnd && > *maRedlineTable[ n+1 ]->Start() != *pREnd ) ) ) branch in DocumentRedlineManager::AppendRedline (sw/source/core/doc/DocumentRedlineManager.cxx). However, when that happened to fail on a minute tick boundary because its > pRedl->CanCombine( *pNewRedl ) && part was false, we would end up with split redline ranges, and SwAutoCorrDoc::ChgAutoCorrWord (sw/source/core/edit/acorrect.cxx) would not execute the autocorrection replacement across those split ranges due to its > // don't replace, if a redline starts or ends within the original text code. (One way of making that test fail reproducibly would be with some > diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx b/sw/qa/extras/uiwriter/uiwriter6.cxx > index 0159c5bf07ed..8716c6a09882 100644 > --- a/sw/qa/extras/uiwriter/uiwriter6.cxx > +++ b/sw/qa/extras/uiwriter/uiwriter6.cxx > @@ -7,6 +7,10 @@ > * file, You can obtain one at http://mozilla.org/MPL/2.0/. > */ > > +#include <sal/config.h> > + > +#include <chrono> > + > #include <com/sun/star/drawing/FillStyle.hpp> > #include <swmodeltestbase.hxx> > #include <cntfrm.hxx> > @@ -33,6 +37,7 @@ > #include <com/sun/star/text/XTextViewCursorSupplier.hpp> > #include <com/sun/star/view/XSelectionSupplier.hpp> > #include <o3tl/cppunittraitshelper.hxx> > +#include <osl/thread.hxx> > #include <swdtflvr.hxx> > #include <comphelper/propertysequence.hxx> > #include <LibreOfficeKit/LibreOfficeKitEnums.h> > @@ -1431,7 +1436,9 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testRedlineAutoCorrect2) > CPPUNIT_ASSERT_EQUAL(sReplaced, getParagraph(1)->getString()); > > // Continue it: > - emulateTyping(rXTextDocument, u"Lorem,... "); > + emulateTyping(rXTextDocument, u"Lorem,..."); > + osl::Thread::wait(std::chrono::seconds(70)); > + emulateTyping(rXTextDocument, u" "); > sReplaced = u"Lorem,... Lorem,… "; > CPPUNIT_ASSERT_EQUAL(sReplaced, getParagraph(1)->getString()); > } patch.) So at least improve SwRedlineData::CanCombine to properly check for a date delta of <= 1 minute. However, that still leaves those tests prone to sporadic failures (even though less likely), if they get delayed for a sufficient amount of time in strategically unfortunate places. Ideally, those autocorrection-related tests (which appear to be the ones in sw/qa/extras/uiwriter/uiwriter6.cxx using emulateTyping) would run with redlining turned off, but many of them explicitly enable redlining, presumably for a reason. With that change, UITest_writer_tests started to fail with > FAIL: test_tdf135018 (trackedChanges.trackedchanges) > ---------------------------------------------------------------------- > Traceback (most recent call last): > File "sw/qa/uitest/writer_tests/trackedChanges.py", line 203, in test_tdf135018 > self.assertEqual(147, len(changesList.getChildren())) > AssertionError: 147 != 111 in a test introduced with b6ab2330d97672936edc56de8d6f5b6f772908ff "tdf#135018: sw: Add UItest". That sw/qa/uitest/data/tdf135018.odt's content.xml contains 147 <text:tracked-changes> <dc:date> elements ranging from 2020-07-11T10:29:12 to 2020-07-21T11:50:32, and apparently some adjacent changes with sufficiently close dates now started to get combined when executing .uno:AcceptTrackedChanges. Change-Id: I1d3453bbf5b0206c080bd3421d525e6b8351f2b7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141653 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sberg...@redhat.com> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141778 Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/qa/uitest/writer_tests/trackedChanges.py b/sw/qa/uitest/writer_tests/trackedChanges.py index e6ed8c67d20b..04834aef0614 100644 --- a/sw/qa/uitest/writer_tests/trackedChanges.py +++ b/sw/qa/uitest/writer_tests/trackedChanges.py @@ -204,7 +204,7 @@ class trackedchanges(UITestCase): with self.ui_test.execute_modeless_dialog_through_command(".uno:AcceptTrackedChanges", close_button="close") as xTrackDlg: changesList = xTrackDlg.getChild("writerchanges") - self.assertEqual(147, len(changesList.getChildren())) + self.assertEqual(111, len(changesList.getChildren())) # Without the fix in place, it would have crashed here xAccBtn = xTrackDlg.getChild("acceptall") @@ -215,7 +215,7 @@ class trackedchanges(UITestCase): xUndoBtn = xTrackDlg.getChild("undo") xUndoBtn.executeAction("CLICK", tuple()) - self.assertEqual(147, len(changesList.getChildren())) + self.assertEqual(111, len(changesList.getChildren())) # Check the changes are shown after opening the Manage Tracked Changes dialog diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx index 9a7e66051bde..002184cd64c0 100644 --- a/sw/source/core/doc/docredln.cxx +++ b/sw/source/core/doc/docredln.cxx @@ -47,6 +47,8 @@ #include <hints.hxx> #include <pamtyp.hxx> #include <poolfmt.hxx> +#include <algorithm> +#include <limits> #include <view.hxx> #include <viewopt.hxx> #include <usrpref.hxx> @@ -1059,16 +1061,24 @@ SwRedlineData::~SwRedlineData() delete m_pNext; } +// Check whether the absolute difference between the two dates is no larger than one minute (can +// give inaccurate results if at least one of the dates is not valid/normalized): +static bool deltaOneMinute(DateTime const & t1, DateTime const & t2) { + auto const & [min, max] = std::minmax(t1, t2); + // Avoid overflow of `min + tools::Time(0, 1)` below when min is close to the maximum valid + // DateTime: + if (min >= DateTime({31, 12, std::numeric_limits<sal_Int16>::max()}, {23, 59})) { + return true; + } + return max <= min + tools::Time(0, 1); +} + bool SwRedlineData::CanCombine(const SwRedlineData& rCmp) const { - DateTime aTime = GetTimeStamp(); - aTime.SetSec(0); - DateTime aCompareTime = rCmp.GetTimeStamp(); - aCompareTime.SetSec(0); return m_nAuthor == rCmp.m_nAuthor && m_eType == rCmp.m_eType && m_sComment == rCmp.m_sComment && - aTime == aCompareTime && + deltaOneMinute(GetTimeStamp(), rCmp.GetTimeStamp()) && m_bMoved == rCmp.m_bMoved && (( !m_pNext && !rCmp.m_pNext ) || ( m_pNext && rCmp.m_pNext &&