Catch2: Word wrapping duplicates words in strings

Created on 4 Oct 2018  路  6Comments  路  Source: catchorg/Catch2

Steps to reproduce

Compile and run the following:

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEST_CASE("Demonstrate the bug in word wrapping") {
    const auto long_string = std::string(
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl \n"
        "massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam in \n"
        "convallis posuere, libero nisi ultricies orci, nec lobortis.\n");

    const auto even_longer_string = long_string + '\n';

    // This will fail; that's intentional.
    REQUIRE(long_string == even_longer_string);
}

When ran, this produces the following output:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.out is a Catch v2.4.1 host application.
Run with -? for options

-------------------------------------------------------------------------------
Demonstrate the bug in word wrapping
-------------------------------------------------------------------------------
main.cpp:4
...............................................................................

main.cpp:19: FAILED:
  REQUIRE( long_string == even_longer_string )
with expansion:
  "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
  massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam in
  in
  convallis posuere, libero nisi ultricies orci, nec lobortis.
  "
  ==
  "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
  massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam in
  in
  convallis posuere, libero nisi ultricies orci, nec lobortis.

  "

===============================================================================
test cases: 1 | 1 failed
assertions: 1 | 1 failed

Notice that this output contains "quam in in convallis", whereas the original code only contains "quam in convallis".

Extra information

  • Catch version: 9e1bdca4667295fcb16265eae00efa8423f07007
  • Operating System: NixOS 18.03
  • Compiler+version: GCC 7.3.0 and Clang 5.0.2

Most helpful comment

After few hours of debugging I found that this is actually issue with clara::TextFlow::Column::iterator formatting with the indentation. In this case the second line has 81 characters which is longer than console width. Basically the problem will occur here

auto operator *() const -> std::string {
               assert( m_stringIndex < m_column.m_strings.size() );
                assert( m_pos <= m_end );
               if( m_pos + m_column.m_width < m_end ) // 155 < 155
                    return addIndentAndSuffix(line().substr(m_pos, m_len));
                else
                    return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); // m_end - m_pos is 79 or m_column.m_width
}

Seems that it should be enough to change the condition to <= instead of <.
With this change the result is:

"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam
in
convallis posuere, libero nisi ultricies orci, nec lobortis.
"
==
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam
in
convallis posuere, libero nisi ultricies orci, nec lobortis.

"

All 6 comments

After few hours of debugging I found that this is actually issue with clara::TextFlow::Column::iterator formatting with the indentation. In this case the second line has 81 characters which is longer than console width. Basically the problem will occur here

auto operator *() const -> std::string {
               assert( m_stringIndex < m_column.m_strings.size() );
                assert( m_pos <= m_end );
               if( m_pos + m_column.m_width < m_end ) // 155 < 155
                    return addIndentAndSuffix(line().substr(m_pos, m_len));
                else
                    return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); // m_end - m_pos is 79 or m_column.m_width
}

Seems that it should be enough to change the condition to <= instead of <.
With this change the result is:

"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam
in
convallis posuere, libero nisi ultricies orci, nec lobortis.
"
==
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam
in
convallis posuere, libero nisi ultricies orci, nec lobortis.

"

@JoeyGrajciar Thanks.

Will you open up a PR against Clara?

@horenmar Yes i will create one soon :) Probably it will be different as i am not really sure if that condition is needed.

This has been fixed in the dependency, now it needs to find its way upward.

Fixed in 779e83bc2080729da97f2890598e898a4c751c9b

Thank you very much!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pwinston picture pwinston  路  5Comments

Viatorus picture Viatorus  路  3Comments

maiermic picture maiermic  路  7Comments

emil-e picture emil-e  路  8Comments

zwcloud picture zwcloud  路  5Comments