#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); }