diff --git a/test/src/test_BufferLineWalker.cc b/test/src/test_BufferLineWalker.cc new file mode 100644 index 0000000..6491ede --- /dev/null +++ b/test/src/test_BufferLineWalker.cc @@ -0,0 +1,180 @@ +#include "gtest/gtest.h" +#include "BufferLineWalker.h" + +class MyCharacterWidthDeterminer : public CharacterWidthDeterminer +{ + int operator()(uint32_t character) + { + if (character < 32) + { + return 2; + } + else + { + return 1; + } + } +} cld; + +TEST(BufferLineWalkerTest, calls_callback_once_for_empty_line) +{ + static const uint8_t data[] = "\n"; + std::shared_ptr b = std::make_shared(data, 1u); + BufferLineWalker blw(b, cld); + blw.set_width(20); + std::shared_ptr start_of_line = b->add_iterator(); + int times_called = 0; + blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { + times_called++; + EXPECT_EQ(0, row_offset); + EXPECT_EQ(0, screen_column); + EXPECT_EQ(0, virtual_column); + EXPECT_EQ(0, character_width); + return true; + }); + EXPECT_EQ(1, times_called); +} + +TEST(BufferLineWalkerTest, walks_correctly_with_tabs_and_no_line_wrapping) +{ + static const char data[] = "\t1\t12\t123\t1234\t!"; + std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); + BufferLineWalker blw(b, cld); + blw.set_width(100); + std::shared_ptr start_of_line = b->add_iterator(); + int times_called = 0; + blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { + EXPECT_EQ(0, row_offset); + static int expected_screen_columns[] = { + 0, 4, 5, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 24, 25 + }; + static int expected_character_widths[] = { + 4, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 0 + }; + EXPECT_LT(times_called, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); + EXPECT_EQ(expected_screen_columns[times_called], screen_column); + EXPECT_EQ(expected_screen_columns[times_called], virtual_column); + EXPECT_EQ(expected_character_widths[times_called], character_width); + times_called++; + return true; + }); + EXPECT_EQ((int)strlen(data) + 1, times_called); +} + +TEST(BufferLineWalkerTest, walks_correctly_with_tabs_and_line_wrapping) +{ + static const char data[] = "\t1\t12\t123\t1234\t!"; + std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); + BufferLineWalker blw(b, cld); + blw.set_width(5); + std::shared_ptr start_of_line = b->add_iterator(); + int times_called = 0; + blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { + static int expected_screen_columns[] = { + 0, 4, 0, 3, 4, 0, 2, 3, 4, 0, 1, 2, 3, 4, 0, 4, 0 + }; + static int expected_row_offsets[] = { + 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5 + }; + static int expected_virtual_columns[] = { + 0, 4, 5, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 24, 25 + }; + static int expected_character_widths[] = { + 4, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 0 + }; + EXPECT_LT(times_called, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); + EXPECT_EQ(expected_row_offsets[times_called], row_offset); + EXPECT_EQ(expected_screen_columns[times_called], screen_column); + EXPECT_EQ(expected_virtual_columns[times_called], virtual_column); + EXPECT_EQ(expected_character_widths[times_called], character_width); + times_called++; + return true; + }); + EXPECT_EQ((int)strlen(data) + 1, times_called); +} + +TEST(BufferLineWalkerTest, walks_correctly_with_multi_column_characters_and_line_wrapping) +{ + static const char data[] = "ab\002xyz\003."; + std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); + BufferLineWalker blw(b, cld); + blw.set_width(4); + std::shared_ptr start_of_line = b->add_iterator(); + int times_called = 0; + blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { + static int expected_screen_columns[] = { + 0, 1, 2, 0, 1, 2, 0, 2, 3 + }; + static int expected_row_offsets[] = { + 0, 0, 0, 1, 1, 1, 2, 2, 2 + }; + static int expected_virtual_columns[] = { + 0, 1, 2, 4, 5, 6, 7, 9, 10 + }; + static int expected_character_widths[] = { + 1, 1, 2, 1, 1, 1, 2, 1, 0 + }; + EXPECT_LT(times_called, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); + EXPECT_EQ(expected_row_offsets[times_called], row_offset); + EXPECT_EQ(expected_screen_columns[times_called], screen_column); + EXPECT_EQ(expected_virtual_columns[times_called], virtual_column); + EXPECT_EQ(expected_character_widths[times_called], character_width); + times_called++; + return true; + }); + EXPECT_EQ((int)strlen(data) + 1, times_called); +} + +TEST(BufferLineWalkerTest, does_not_push_down_a_row_when_a_multi_column_character_is_wider_than_view_width) +{ + static const char data[] = "\002\003"; + std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); + BufferLineWalker blw(b, cld); + blw.set_width(1); + std::shared_ptr start_of_line = b->add_iterator(); + int times_called = 0; + blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { + static int expected_screen_columns[] = { + 0, 0, 0 + }; + static int expected_row_offsets[] = { + 0, 1, 2 + }; + static int expected_virtual_columns[] = { + 0, 2, 4 + }; + static int expected_character_widths[] = { + 2, 2, 0 + }; + EXPECT_LT(times_called, (int)(sizeof(expected_screen_columns)/sizeof(expected_screen_columns[0]))); + EXPECT_EQ(expected_row_offsets[times_called], row_offset); + EXPECT_EQ(expected_screen_columns[times_called], screen_column); + EXPECT_EQ(expected_virtual_columns[times_called], virtual_column); + EXPECT_EQ(expected_character_widths[times_called], character_width); + times_called++; + return true; + }); + EXPECT_EQ((int)strlen(data) + 1, times_called); +} + +TEST(BufferLineWalkerTest, stops_iterating_when_callback_returns_false) +{ + static const char data[] = "abcdef"; + std::shared_ptr b = std::make_shared((const uint8_t *)data, strlen(data)); + BufferLineWalker blw(b, cld); + blw.set_width(6); + std::shared_ptr start_of_line = b->add_iterator(); + int times_called = 0; + blw.walk_line(*start_of_line, [×_called](int row_offset, int screen_column, int virtual_column, int character_width, const Buffer::Iterator & it) -> bool { + times_called++; + if (times_called >= 3) + { + return false; + } + else + { + return true; + } + }); + EXPECT_EQ(3, times_called); +}