[libcalamares] Test some degenerate truncation cases

This commit is contained in:
Adriaan de Groot 2021-02-02 15:35:53 +01:00
parent 7ab9c63903
commit eafb8149b3
3 changed files with 39 additions and 17 deletions

View File

@ -135,14 +135,15 @@ truncateMultiLine( const QString& string, CalamaresUtils::LinesStartEnd lines, C
return shorter; return shorter;
} }
const int linesInString = string.count( NEWLINE ) + ( string.endsWith( NEWLINE ) ? 0 : 1 ); const int physicalLinesInString = string.count( NEWLINE );
if ( ( string.length() <= chars.total ) && ( linesInString <= maxLines ) ) const int logicalLinesInString = physicalLinesInString + ( string.endsWith( NEWLINE ) ? 0 : 1 );
if ( ( string.length() <= chars.total ) && ( logicalLinesInString <= maxLines ) )
{ {
return string; return string;
} }
QString front, back; QString front, back;
if ( string.count( NEWLINE ) >= maxLines ) if ( physicalLinesInString >= maxLines )
{ {
int from = -1; int from = -1;
for ( int i = 0; i < lines.atStart; ++i ) for ( int i = 0; i < lines.atStart; ++i )
@ -174,6 +175,22 @@ truncateMultiLine( const QString& string, CalamaresUtils::LinesStartEnd lines, C
back = string.right( lastNewLine ); back = string.right( lastNewLine );
} }
} }
else
{
// We have: <= maxLines and longer than chars.total, so:
// - carve out a chunk in the middle, based a little on
// how the balance of atStart and atEnd is
const int charsToChop = string.length() - chars.total;
if ( charsToChop < 1 )
{
// That's strange, again
return string;
}
const int startPortion = charsToChop * lines.atStart / maxLines;
const int endPortion = charsToChop * lines.atEnd / maxLines;
front = string.left( string.length() / 2 - startPortion );
back = string.right( string.length() / 2 - endPortion );
}
if ( front.length() + back.length() <= chars.total ) if ( front.length() + back.length() <= chars.total )
{ {
@ -200,7 +217,7 @@ truncateMultiLine( const QString& string, CalamaresUtils::LinesStartEnd lines, C
} }
// Both are non-empty, so nibble away at both of them // Both are non-empty, so nibble away at both of them
front.truncate( chars.total / 2 ); front.truncate( chars.total / 2 );
if ( !front.endsWith( NEWLINE ) ) if ( !front.endsWith( NEWLINE ) && physicalLinesInString > 0 )
{ {
front.append( NEWLINE ); front.append( NEWLINE );
} }

View File

@ -89,6 +89,8 @@ struct CharCount
* @p lines.atStart is zero) or end (if @p lines.atEnd is zero) or in the middle * @p lines.atStart is zero) or end (if @p lines.atEnd is zero) or in the middle
* (if both are nonzero). * (if both are nonzero).
* *
* Asking for 0 lines will make this behave like QString::truncate().
*
* @param string the input string. * @param string the input string.
* @param lines number of lines to preserve. * @param lines number of lines to preserve.
* @param chars maximum number of characters in the returned string. * @param chars maximum number of characters in the returned string.

View File

@ -676,33 +676,36 @@ and the translations updated.)" );
} }
} }
void LibCalamaresTests::testStringTruncationDegenerate() void
LibCalamaresTests::testStringTruncationDegenerate()
{ {
Logger::setupLogLevel( Logger::LOGDEBUG ); Logger::setupLogLevel( Logger::LOGDEBUG );
using namespace CalamaresUtils; using namespace CalamaresUtils;
// This is quite long, 1 line only, with no newlines // This is quite long, 1 line only, with no newlines
const QString longString( const QString longString( "The portscout new distfile checker has detected that one or more of your "
"The portscout new distfile checker has detected that one or more of your" "ports appears to be out of date. Please take the opportunity to check "
"ports appears to be out of date. Please take the opportunity to check" "each of the ports listed below, and if possible and appropriate, "
"each of the ports listed below, and if possible and appropriate," "submit/commit an update. If any ports have already been updated, you can "
"submit/commit an update. If any ports have already been updated, you can"
"safely ignore the entry." ); "safely ignore the entry." );
const char NEWLINE = '\n'; const char NEWLINE = '\n';
const int quiteShort = 16; const int quiteShort = 16;
QVERIFY( longString.length() > quiteShort); QVERIFY( longString.length() > quiteShort );
QVERIFY( !longString.contains(NEWLINE)); QVERIFY( !longString.contains( NEWLINE ) );
QVERIFY( longString.indexOf(NEWLINE) < 0); QVERIFY( longString.indexOf( NEWLINE ) < 0 );
{ {
auto s = truncateMultiLine( longString, LinesStartEnd { 1, 0 }, CharCount { quiteShort } ); auto s = truncateMultiLine( longString, LinesStartEnd { 1, 0 }, CharCount { quiteShort } );
cDebug() << "Result-line" << Logger::Quote << s; cDebug() << "Result-line" << Logger::Quote << s;
QVERIFY( s.length() > 1 ); QVERIFY( s.length() > 1 );
QCOMPARE( s.length(), quiteShort); // Newline between front and back part QCOMPARE( s.length(), quiteShort ); // No newline between front and back part
QVERIFY( s.startsWith( "The " ) ); QVERIFY( s.startsWith( "The port" ) ); // 8, which is quiteShort / 2
QVERIFY( s.endsWith( "entry." ) ); QVERIFY( s.endsWith( "e entry." ) ); // also 8 chars
auto t = truncateMultiLine( longString, LinesStartEnd { 2, 2 }, CharCount { quiteShort } );
QCOMPARE( s, t );
} }
} }